Both wait() and waitpid() have a non-blocking mode (WNOHANG). So use SIGCHLD to decide when to check the status of the child processes, and waitpid() to actually do it.
There is a not-so-nice but very effective trick: Send the process you wish to check for a signal of '0' (using kill(pid, 0)), if that fails the process no longer exists.
This is kind of nasty in case your pids tick over very fast so you'd have to do this with a fairly high frequency to make sure you don't hit the same pid twice.
Fortunately this is hardly ever a problem but it is something worth thinking about when using the trick.