cerrno

C poll() returns ECHILD


Just encountered an undocumented error. The call to poll() returned ECHILD.

I have a very simple code, almost directly from the man:

struct pollfd fds[] = { fd, POLLIN, 0 };
while(should_continue) {
  int rc=poll(fds, 1, 1000);
  if(rc==0) {
     // exit by timeout, repeat waiting
     continue;
  } else if(rc<0) {
     printf("poll error %d\n", errno);
     exit(1);
  }
  // read from fd
}

This code suddenly exited with "poll error 10". But man 2 poll does not even mention ECHILD as possible error. What could be the cause?


Solution

  • I suspect that you have a signal handler that clobbers errno. Specifically, a SIGCHLD handler that calls wait until it returns -1.

    What happens is this:

    1. You call poll and it blocks.
    2. A child exits.
    3. poll returns error EINTR to allow your signal handler a chance to run.
    4. Your SIGCHLD handler is called.
    5. It calls wait repeatedly to reap every child waiting to be reaped.
    6. The last call to wait, having nothing left to reap, returns error ECHILD.
    7. Your SIGCHLD handler returns without restoring errno.
    8. poll appears to have returned error ECHILD when it really returned error EINTR.

    Fix:

    Very few things return error ECHILD, so the possible explanations are very limited. As such, I'm pretty confident in my guess.


    Notes: