[질문] fork 후 signal 을 이용한 좀비처리.

psjHello의 이미지

fork() 로 생성되어진 자식프로세스가
작업을 마치고 SIGCHLD 를 발생시키고
죽었을때,

signal (SIGCHLD, (void*) zombie_remover);

를 사용해서 좀비처리를 하려고 합니다.

fork() 가 어느정도 여유를 두고 호출될 경우에는
만족스럽게 동작합니다만...

소켓으로 서버를 짜던 도중,
소켓클라이언트로 부터 '한꺼번에 많은 요청' 을 받게되어
짧은 시간내에 많은 fork() 를 호출해야 할 경우에
좀비들이 많이 생겨나는데요...

자식이 죽을때마다, 죽는자식의 정확한 수만큼
SIGCHLD 를 받아서, 정확한 수만큼 핸들러를
호출하는 것이 아닌지 궁금하네요.

---------------------------
의심이 가는건, 프로그램이 블록된 상태에선
중복된 signal 이 중간중간 drop 되어진다는 것을
어디선가 들은것 밖에 없는데요...

---------------------------
저 같은 경우에
'signal(SIGCHLD ....) 外에, 또 다른 좀비제거-루틴'
을 <두 개 모두 같이> 사용해도 괜찮은 것인지요...

답변 달아주시면 감사하겠습니다...

bw001730의 이미지

시그널이 프로세스에 도착했을때..
만약 프로세스가 이 시그널을 블럭킹하기로 설정했다면
이 시그널은 프로세스의 '시그널대기큐'에 저장됩니다.

기본적인 사항...........을 먼저 말씀드리면...
근데...이 시그널 대기큐에는 같은 종류의 시그널이
여러개 있는 경우는 없습니다. 한 종류마다 최대 한개입니다.
여러개 도착해도 쌓이지 않는 다는 것이죠

옵션적인 사항........
근데...쌓이게 할수도 있습니다.
SA_NODEFER 플래그를 설정해서 가능합니다.

한가지 ..여러 문서들을 읽어보면...더이상 signal 함수를
사용하지 말것을 권장하고 있습니다.
signal 함수를 통해서는 SA_NODEFER 플래그를 설정할
방법이 없거든요
signal 함수는 옛날의 코드와 호환성을 위해 남겨둔 함수라고 합니다.

sigaction 함수를 사용하라고 하네요.
sigaction 함수는 포직스 표준으로...
솔라리스,리눅스, BSD등의 운영체제들이 잘~ 따르고 있는
표준입니다.
sigaction 함수를 사용하면 SA_NODEFER 플래그를 설정할 수 있습니다.
man sigaction 하면 잘나옵니다.

저도 궁금해서 테스트 해보았는데요
리눅스에서 SIGCHLD는 다른 시그널과 마찬가지로
대기큐에 한번만 쌓이게 됩니다. 하지만 SA_NODEFER 플래그를 설정하면
도착한 시그널의 개수만큼...( 큐에 쌓여서 ) 핸들러를 호출해줍니다.

솔라리스7 에서는 기본으로 SIGCHLD는 명시하지 않는다해도
SA_NODEFER 플래그를 설정한 것과 동일한 동작을 하네요

제생각에 리눅스든 솔라리스 7이든.. SIGCHLD개수만큼
핸들러를 호출하려면
SA_NODEFER 플래그를 설정하면 동작이 잘될것 같습니다.

다른 OS에서는 테스트 못해봤습니다.
참고로 제가 테스트 해본 코드입니다.
잘못된부분있으면 알려주시면 감사드리겠습니다.

// 사용자 시그널 핸들러 함수
void catch_sigchld(int signo) 
{ 
    puts("###( Parent ) catch SIGCHLD ");
}

int main(int argc, char *argv[])
{
    int i,n;
    struct sigaction sact;
    sact.sa_flags = 0|SA_NODEFER;
    sigemptyset(&sact.sa_mask);

    // 시그널 핸들러 등록
    sact.sa_handler = catch_sigchld;// 사용자 핸들러 등록
    sigaction(SIGCHLD, &sact, NULL);

    // 자식 프로세스 5개 생성
    for(i=0; i<5; i++) {
        if(fork()==0) {
// 잠시 슬립, 5초후에는 5개의ㅣ 프로세스가 동시에 SIGCHLD를 부모에게 전송함
            sleep(5); 
            printf("(%d번 Child),PID=%d,PPID=%d Exited\n",i,getpid(), getppid());
            exit(13); // 종료값 13번
        }
    }

    sleep(10); // 모든 자식이 종료하여 SIGCHLD를 날리기를 기다림
    exit(0);
pynoos의 이미지

waitpid로 검색해보시죠.. :)

거의 FAQ 입니다..

partout의 이미지

시그널 핸들에서 다음과 같이 써 보세요.

while (waitpid(-1, NULL, WNOHANG) > 0) (void *)0;

어찌나 졸린지..~~

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.