[英]Catching SIGCHLD using sigtimedwait() on BSD
我在使用sigtimedwait()捕獲FreeBSD上的SIGCHLD信號時遇到麻煩。 以下資源在Debian GNU / Linux 7上運行良好,但為我提供了FreeBSD 9.1上暫時不可用的資源:
#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;
}
在Linux上的輸出:
SIGCHLD is 17
received signal 17 from 27600 with status 123
在FreeBSD上的輸出:
SIGCHLD is 20
sigtimedwait failed: Resource temporarily unavailable
在BSD上使用signal()可以正常工作,但這不是我想要的。 我想念什么?
我認為這是FreeBSD中的內核/庫錯誤。 sigtimedwait似乎未報告該信號,因為默認情況下會忽略它。 所以你可以做兩件事
為SIGCHLD事件安裝信號處理程序。 即使由於阻塞信號而從未調用過它,也可以解決該錯誤。
將kqueue與EVFILT_SIGNAL一起使用絕對可以在這種情況下使用,但不能移植(因此需要ifdef)
對於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.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.