Я нашел ответ на этот вопрос, изучив исходный код telnetd, находящийся в пакете GNU inetutils. В telnetd они используют обработчик SIGCHLD, например:
int status;
pid_t pid = waitpid((pid_t)-1, &status, WNOHANG);
syslog (LOG_INFO, "child process %ld exited: %d",
(long) pid, WEXITSTATUS(status));
// do cleanup code