Search code examples
clinuxeventsconcurrencycondition-variable

How to wait for 2 types of events in a loop (C)?


I am trying to wait on waitpid() and read() in a while-true loop. Specifically, I am waiting for either one of these two events and then process it in each iteration of the loop. Currently, I have the following implementation (which is not I desired).

while (true) {
  pid_t pid = waitpid(...);
  process_waitpid_event(...);

  ssize_t sz = read(socket, ....);
  process_read_event(...);
}

The problem with this implementation is that the processing of the second event depends on the completion of the first event. Instead of processing these two events sequentially, I wish to process whichever event that comes first in each iteration of the loop. How should I do this?


Solution

  • If you don't want to touch threading, you can include this in the options of the call to waitpid:

    pid_t pid = waitpid(pid, &status, WNOHANG);
    

    As from the manpage for waitpid:

    WNOHANG - return immediately if no child has exited.

    As such, if waitpid isn't ready, it won't block and the program will just keep going to the next line.

    As for the read, if it is blocking you might want to have a look at poll(2). You can essentially check to see if your socket is ready every set interval, e.g. 250ms, and then call read when it is. This will allow it to not block.

    Your code might look a bit like this:

    // Creating the struct for file descriptors to be polled.
    struct pollfd poll_list[1];
    poll_list[0].fd = socket_fd;
    poll_list[0].events = POLLIN|POLLPRI;
    // POLLIN  There is data to be read
    // POLLPRI There is urgent data to be read
    
    /* poll_res  > 0: Something ready to be read on the target fd/socket.
    ** poll_res == 0: Nothing ready to be read on the target fd/socket.
    ** poll_res  < 0: An error occurred. */
    poll_res = poll(poll_list, 1, POLL_INTERVAL);
    

    This is just assuming that you're reading from a socket, judging from the variable names in your code. As others have said, your problem might require something a bit more heavy duty like threading.