static FILE * find_logfile_handle(void) { pid_t pid; int i; unsigned int j; pid = getpid(); if (pid == initpid) return mainlogfile; if (pid == shm->mainpid) return mainlogfile; if (pid == watchdog_pid) return mainlogfile; i = find_pid_slot(pid); if (i != PIDSLOT_NOT_FOUND) return shm->logfiles[i]; else { /* try one more time. FIXME: This is awful. */ sleep(1); i = find_pid_slot(pid); if (i != PIDSLOT_NOT_FOUND) return shm->logfiles[i]; outputerr("## Couldn't find logfile for pid %d\n", pid); dump_pid_slots(); outputerr("## Logfiles for pids: "); for_each_pidslot(j) outputerr("%p ", shm->logfiles[j]); outputerr("\n"); } return NULL; }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; int fd; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the pidslot it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_pid_slots(); exit(EXIT_FAILURE); } if (logging == TRUE) { fd = fileno(shm->logfiles[pidslot]); if (ftruncate(fd, 0) == 0) lseek(fd, 0, SEEK_SET); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->mainpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; outputerr(BUGTXT "parent (%d) went away!\n", shm->mainpid); sleep(20000); } } /* Wait for all the children to start up. */ while (shm->ready == FALSE) sleep(1); init_child(pidslot); ret = child_process(pidslot); output(1, "child exiting.\n"); _exit(ret); } shm->running_childs++; debugf("Created child %d in pidslot %d [total:%d/%d]\n", shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
static void handle_child(pid_t childpid, int childstatus) { unsigned int i; int slot; switch (childpid) { case 0: //debugf("Nothing changed. children:%d\n", shm->running_childs); break; case -1: if (shm->exit_reason != STILL_RUNNING) return; if (errno == ECHILD) { debugf("All children exited!\n"); for_each_pidslot(i) { if (shm->pids[i] != EMPTY_PIDSLOT) { if (pid_alive(shm->pids[i]) == -1) { debugf("Removing %d from pidmap\n", shm->pids[i]); shm->pids[i] = EMPTY_PIDSLOT; shm->running_childs--; } else { debugf("%d looks still alive! ignoring.\n", shm->pids[i]); } } } break; } output(0, "error! (%s)\n", strerror(errno)); break; default: debugf("Something happened to pid %d\n", childpid); if (WIFEXITED(childstatus)) { slot = find_pid_slot(childpid); if (slot == PIDSLOT_NOT_FOUND) { /* If we reaped it, it wouldn't show up, so check that. */ if (shm->last_reaped != childpid) { outputerr("## Couldn't find pid slot for %d\n", childpid); shm->exit_reason = EXIT_LOST_PID_SLOT; dump_pid_slots(); } } else { debugf("Child %d exited after %ld syscalls.\n", childpid, shm->child_syscall_count[slot]); reap_child(childpid); } break; } else if (WIFSIGNALED(childstatus)) { switch (WTERMSIG(childstatus)) { case SIGALRM: debugf("got a alarm signal from pid %d\n", childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("got a signal from pid %d (%s)\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("** Child got an unhandled signal (%d)\n", WTERMSIG(childstatus)); break; } break; } else if (WIFSTOPPED(childstatus)) { switch (WSTOPSIG(childstatus)) { case SIGALRM: debugf("got an alarm signal from pid %d\n", childpid); break; case SIGSTOP: debugf("Sending PTRACE_DETACH (and then KILL)\n"); ptrace(PTRACE_DETACH, childpid, NULL, NULL); kill(childpid, SIGKILL); reap_child(childpid); break; case SIGFPE: case SIGSEGV: case SIGKILL: case SIGPIPE: case SIGABRT: debugf("Child %d was stopped by %s\n", childpid, strsignal(WTERMSIG(childstatus))); reap_child(childpid); break; default: debugf("Child %d was stopped by unhandled signal (%s).\n", childpid, strsignal(WSTOPSIG(childstatus))); break; } break; } else if (WIFCONTINUED(childstatus)) { break; } else { output(0, "erk, wtf\n"); } }
/* Generate children*/ static void fork_children(void) { while (shm->running_childs < max_children) { int pidslot; int pid = 0; if (shm->spawn_no_more == TRUE) return; /* a new child means a new seed, or the new child * will do the same syscalls as the one in the pidslot it's replacing. * (special case startup, or we reseed unnecessarily) */ if (shm->ready == TRUE) reseed(); /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { outputerr("## Pid map was full!\n"); dump_pid_slots(); exit(EXIT_FAILURE); } if (logging == TRUE) { int fd; fd = fileno(shm->logfiles[pidslot]); if (ftruncate(fd, 0) == 0) lseek(fd, 0, SEEK_SET); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid == 0) { /* Child process. */ init_child(pidslot); child_process(pidslot); debugf("child %d exiting.\n", pidslot); _exit(EXIT_SUCCESS); } else { if (pid == -1) { output(0, "couldn't create child! (%s)\n", strerror(errno)); shm->exit_reason = EXIT_FORK_FAILURE; exit(EXIT_FAILURE); } } shm->pids[pidslot] = pid; shm->running_childs++; debugf("Created child %d in pidslot %d [total:%d/%d]\n", shm->pids[pidslot], pidslot, shm->running_childs, max_children); if (shm->exit_reason != STILL_RUNNING) return; } shm->ready = TRUE; debugf("created enough children\n"); }
static void fork_children(void) { int pidslot; static char childname[17]; /* Generate children*/ while (shm->running_childs < shm->max_children) { int pid = 0; /* Find a space for it in the pid map */ pidslot = find_pid_slot(EMPTY_PIDSLOT); if (pidslot == PIDSLOT_NOT_FOUND) { printf("[%d] ## Pid map was full!\n", getpid()); dump_pid_slots(); exit(EXIT_FAILURE); } (void)alarm(0); fflush(stdout); pid = fork(); if (pid != 0) shm->pids[pidslot] = pid; else { /* Child process. */ int ret = 0; mask_signals_child(); memset(childname, 0, sizeof(childname)); sprintf(childname, "trinity-child%d", pidslot); prctl(PR_SET_NAME, (unsigned long) &childname); oom_score_adj(500); /* Wait for parent to set our pidslot */ while (shm->pids[pidslot] != getpid()) { /* Make sure parent is actually alive to wait for us. */ ret = pid_alive(shm->parentpid); if (ret != 0) { shm->exit_reason = EXIT_SHM_CORRUPTION; printf("[%d] " BUGTXT "parent (%d) went away!\n", getpid(), shm->parentpid); sleep(20000); } } init_child(pidslot); ret = child_process(pidslot); output(1, "child %d exiting\n", getpid()); _exit(ret); } shm->running_childs++; debugf("[%d] Created child %d in pidslot %d [total:%d/%d]\n", getpid(), shm->pids[pidslot], pidslot, shm->running_childs, shm->max_children); if (shm->exit_reason != STILL_RUNNING) return; } debugf("[%d] created enough children\n", getpid()); }