Is there a version of the wait() system call that sets a timeout?

前端 未结 3 1539
悲&欢浪女
悲&欢浪女 2020-12-07 02:31

Is there any way to use the wait() system call with a timeout, besides using a busy-waiting or busy-sleeping loop?

I\'ve got a parent process that

相关标签:
3条回答
  • 2020-12-07 02:57

    You can use waitpid together with the WNOHANG option and a sleep.

    while(waitpid(pid, &status, WNOHANG) == 0) {
        sleep(1);
    }
    

    But this will be an active sleeping. However I see no other way using the wait type of functions.

    0 讨论(0)
  • 2020-12-07 03:11

    On linux, you can also solve this problem using signalfd. signalfd essentially takes a set of signals and creates an fd which you can read; each block you read corresponds to a signal which has fired. (You should block these signals with sigprocmask so that they are not actually sent.)

    The advantage of signalfd is that you can use the fd with select, poll, or epoll, all of which allow for timeouts, and all of which allow you to wait for other things as well.

    One note: If the same signal fires twice before the corresponding struct signalfd_siginfo is read, you'll only receive a single indication. So when you get a SIGCHLD indication, you need to waitpid(-1, &status, &WNOHANG) repeatedly until it returns -1.

    On FreeBSD, you can achieve the same effect rather more directly using kqueue and a kevent of type EVFILT_PROC. (You can also kqueue a SIGCHLD event, but EVFILT_PROC lets you specify the events by child pid instead of globally for all children.) This should also work on Mac OS X, but I've never tried it.

    0 讨论(0)
  • 2020-12-07 03:24

    There's not a wait call that takes a timeout.

    What you can do instead is install a signal handler that sets a flag for SIGCHLD, and use select() to implement a timeout. select() will be interrupted by a signal.

    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
    }
    

    More logic is needed if you have other signal you need to handle as well though

    0 讨论(0)
提交回复
热议问题