2013-06-09 11 views
0

FreeBSD에서 SIGCHLD 신호를 잡는 데 sigtimedwait()을 사용하는 데 문제가 있습니다. 다음 소스/리눅스 7 데비안 GNU에서 잘 작동하지만 나에게 FreeBSD의 9.1에 일시적으로 사용할 수없는 자원 제공 : 리눅스에BSD에서 sigtimedwait()을 사용하여 SIGCHLD 잡기

#include <stdio.h> 
#include <signal.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <time.h> 

int main() { 
     sigset_t set; 
     pid_t pid; 

     printf("SIGCHLD is %i\n", SIGCHLD); 

     sigemptyset(&set); 
     sigaddset(&set, SIGCHLD); 
     sigprocmask(SIG_BLOCK, &set, NULL); 

     pid = fork(); 

     if(pid == -1) { 
       printf("fork failed: %s\n", strerror(errno)); 
       exit(1); 
     } else if(pid) { 
       sigset_t set2; 
       siginfo_t siginfo; 
       struct timespec timeout = {3, 0}; 
       int signal; 

       sigemptyset(&set2); 
       sigaddset(&set2, SIGCHLD); 

       signal = sigtimedwait(&set2, &siginfo, &timeout); 

       if(signal == -1) { 
         printf("sigtimedwait failed: %s\n", strerror(errno)); 
         exit(2); 
       } else { 
         printf("received signal %i from %i with status %i\n", signal, siginfo.si_pid, siginfo.si_status); 
       } 
     } else { 
       sleep(1); 
       exit(123); 
     } 

     return 0; 
} 

출력 : FreeBSD의에

SIGCHLD is 17 
received signal 17 from 27600 with status 123 

출력 :

SIGCHLD is 20 
sigtimedwait failed: Resource temporarily unavailable 

signal()을 사용하면 BSD에서 잘 작동하지만 이것은 내가 원하는 것만은 아니다. 내가 뭘 놓치고 있니?

답변

0

저는 이것이 FreeBSD의 커널/라이브러리 버그라고 생각합니다. sigtimedwait는 기본적으로 무시되므로 신호를보고하지 않는 것 같습니다. 그래서 당신은 2 가지를 할 수 있습니다.

  1. SIGCHLD 이벤트를위한 신호 처리기를 설치하십시오. 신호를 차단하고 있기 때문에 결코 호출되지 않습니다. 버그를 해결할 수 있습니다. 확실히이 경우에 작동하지만 이식 할 수 없습니다 EVFILT_SIGNAL와

  2. 사용 kqueue는 2의

, 여기에 해당하는 코드

 int kq = kqueue(); 
    struct kevent ke; 
    EV_SET(&ke, SIGCHLD, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); 
    kevent(kq, &ke, 1, NULL, 0, NULL); 
    if (kevent(kq, NULL, 0, &ke, 1, &timeout) == 1) { 
      signal = ke.ident; 
    } 
    else { 
     // Catches errors in the add, timeout, and kevent wait 
     signal = -1; 
    } 
    close(kq); 
    // note that siginfo is not populated, there is no way to populate it using kqueue. 
이다 (그래서 당신은 IFDEF이 필요로하는 것)