除了使用忙等待或忙碌睡眠循环之外,有没有办法在超时时使用wait()
系统调用?
我有一个父进程,fork
本身,exec
是子可执行文件。然后它等待孩子完成,通过适当的方式抓取其输出,并执行进一步处理。如果进程未在一段时间内完成,则假定其执行超时,并执行其他操作。不幸的是,鉴于问题的性质,这种超时检测是必要的。
答案 0 :(得分:6)
没有等待超时的等待电话。
您可以做的是安装一个为SIGCHLD设置标志的信号处理程序,并使用select()来实现超时。 select()将被信号中断。
static volatile int punt;
static void sig_handler(int sig)
{
punt = 1;
}
...
struct timeval timeout = {10,0};
int rc;
signal(SIGCHLD, sig_handler);
fork/exec stuff
//select will get interrupted by a signal
rc = select(0, NULL,NULL,NULL, &timeout );
if (rc == 0) {
// timed out
} else if (punt) {
//child terminated
}
如果您还需要处理其他信号,则需要更多逻辑
答案 1 :(得分:3)
您可以将waitpid
与WNOHANG
选项一起使用并休眠。
while(waitpid(pid, &status, WNOHANG) == 0) {
sleep(1);
}
但这将是一个积极的睡眠。但是我没有看到使用wait
类型函数的其他方式。
答案 2 :(得分:3)
在linux上,您还可以使用signalfd
解决此问题。 signalfd
基本上采用一组信号并创建一个你可以阅读的fd;您读取的每个块对应于已触发的信号。 (您应该使用sigprocmask阻止这些信号,以便它们不会被实际发送。)
signalfd
的优势在于您可以将fd与select
,poll
或epoll
一起使用,所有这些都允许超时,并且所有这些都允许你也要等待其他事情。
一个注意事项:如果相同的信号在读取相应的struct signalfd_siginfo
之前触发两次,则只会收到一个指示。因此,当您收到SIGCHLD
指示时,需要反复waitpid(-1, &status, &WNOHANG)
,直到它返回-1。
在FreeBSD上,您可以使用kqueue
和kevent
类型EVFILT_PROC
更直接地实现相同的效果。 (您也可以使用SIGCHLD事件,但EVFILT_PROC允许您通过子pid指定事件,而不是全局子项指定事件。)这也适用于Mac OS X,但我从未尝试过。