static void send_child(unsigned i, char *line, char **cols) { const char *p; struct iovec iov[2]; size_t l=strlen(line); module_delids[i]=0; for (p=MODULEDEL_DELID(cols); *p >= '0' && *p <= '9'; p++) module_delids[i] = module_delids[i] * 10 + (*p - '0'); if (info[i].pid < 0) /* Failure in start_child */ { terminated_child(i, module_delids[i]); return; } iov[0].iov_base=(caddr_t)line; iov[0].iov_len=l; iov[1].iov_base="\n"; iov[1].iov_len=1; if (writev(info[i].cmdpipe, iov, 2) != l+1) { clog_msg_prerrno(); /* This is usually because the process has terminated, ** but we haven't cleaned this up yet, but just make sure. */ kill(info[i].pid, SIGKILL); } info[i].isbusy=1; }
static void clean_zombies() { int pid, wstat; while ((pid = waitpid(-1, &wstat, WNOHANG)) > 0) { /* did this child terminate? */ if (WIFEXITED(wstat) || WIFSIGNALED(wstat)) { #ifdef MC_DEBUG if (WIFEXITED(wstat)) Dprintf("child %d terminated with %d\n", pid, WEXITSTATUS(wstat)); else Dprintf("child %d terminated by signal %d\n", pid, WTERMSIG(wstat)); #endif /* we can only flag at this point, since actually removing the child would cause re-entrance issues. So we let fork/collect clean up the child list. */ terminated_child(pid); } } }