쓰레드 환경에서 waitpid에 관해서.. ?

partout의 이미지

하나의 쓰레드에서 차일드 프로세스를 생성하고,
다른 쓰레드에서 이 차일드 프로세스에 대해서 wait하면.. wait이 실패하더군요.

가령, 프로그램이 구동될 때 작업 쓰레드를 하나 생성하는데...
이 작업 쓰레드가 쓰레드는 파일에 기록된 이전 상태를 확인하고
필요한 경우 차일드 프로세스를 fork합니다.
이 후에 사용자로부터 접속이 있으면 이를 처리하기 위한 핸들러 쓰레드가
하나 생성되고, 사용자가 현재 구동 중인 차일드 프로세스를 종료시키기를 원하면
TERM 시그널을 날려 프로세스를 종료시키고, 좀비를 막기 위해 waitpid를
호출합니다. 문제는 여기 waitpid에서 항상 실패합니다.
errno 값을 찍어 봤는데 ECHILD(10)이더군요. waitpid 하려는 프로세스가
자신의 child가 아니라는 것 같은데...
이것은 리눅스의 쓰레드가 쓰레드마다 하나의 프로세스를 할당하기 때문에
다른 쓰레드가 fork한 차일드 프로세스를 자신의 차일드 프로세스로
인식하지 못하는 것 때문인 것 같더군요.

저는 이러한 상황을 좀 깔끔하게 해결할 수 있는 방법이 궁금합니다.
그냥 저는 작업 쓰레드 쪽에서 주기적으로 waitpid를 호출해서 좀비를
해결할까도 생각해 봤는데,... 그것보다 더 좋은 방법이 있을 것 같아서..
가령.. 다른 쓰레드에서 생성한 차일드 프로세스를 자신의 아이로 인식시킨다던가...

답변 부탁 드립니다.

yaang_kr의 이미지

ECHILD 는 리턴할 값이 없을때 errno에 세팅됩니다.
쉽게 말해 SIGCHLD가 오지 않았다는..

SIGCHLD를 sigismember로 시그널 마스킹 했는지 확인해보시죠.

SIGPFE, SIGSEGV같은 동기화 "하드웨워"문맥 시그널을 해당하지
않으면 어느 쓰레드로 시그널이 전달될지 알수 없습니다.
즉 SIGCHLD는 어느 쓰레드로 전달될지 장담 할수 없습니다.

일반적으로는 메인쓰레드에서 pthread_sigmask 를 통해 시그널을 마스킹 하고 다른 전담 쓰레드에서 sigwait를 통해 시그널을 동기적으로 처리하는것을 권고 하고 있습니다.( POSIX THREAD PROGRAMING )

브이 V

partout의 이미지

답변에 감사 드립니다. 많은 도움이 되었습니다. ^^

하지만, 정작 문제가 되었던 부분은 해결을 하지 못했습니다.

말씀하신대로 모든 쓰레드에서 시그널을 masking하고
시그널 처리를 전담할 쓰레드에서 아래와 같이 작성된 함수를
호출해서 시그널을 처리하도록 했습니다.

static void handleSignals()
{

    sigset_t    signal_set;
    int         sig;

    sigemptyset(&signal_set);
    sigaddset(&signal_set, SIGCHLD);
    sigaddset(&signal_set, SIGTERM);
    sigaddset(&signal_set, SIGQUIT);
    sigaddset(&signal_set, SIGINT);
    sigaddset(&signal_set, SIGHUP);
    sigaddset(&signal_set, SIGPIPE);

    pthread_sigmask(SIG_BLOCK, &signal_set, NULL);

    while (1) {

        sigwait(&signal_set, &sig);
        switch (sig) {

            case SIGCHLD:
                while (waitpid(-1, NULL, WNOHANG) > 0) (void *)0;
                break;

            case SIGTERM:
            case SIGQUIT:
            case SIGINT:
            case SIGHUP:
                onExit(sig);
                break;

            case SIGPIPE:
                // ignore
                break;

            default:
                break;
        }
    }
}

하지만, 문제는 다른 쓰레드에서 생성한 차일드 프로세스를
종료시켰을 경우에 이 전담 쓰레드로 시그널이 전달되지 않네요.
차일드 프로세스가 종료되었을 때 SIGCHLD 시그널은 차일드를
생성한 프로세스가 아니라 차일드 프로세스를 생성했던 쓰레드로만
전달이 되는 것 같습니다. 단지 추측이라 맞는 얘기인지 모르겠네요.

혹시, 이 부분에 대해서 아시면 답변 부탁드리겠습니다.
이런 상황을 해결할 수 있는 방법에 대해서도 답변해 주시면 더 감사하구요. ^^

어찌나 졸린지..~~

partout의 이미지

마땅한 해결책을 찾지 못해서... 처음 생각했던대로..
차일드를 포크하는 작업 쓰레드에서 주기적으로
아래와 같은 구문을 실행시켜서 zombie를
정리하도록 했습니다.

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.