static bool wait_for_shmready(void) { while (shm->ready == FALSE) { unsigned int counter = 0; if (shm->mainpid != 0) { if (check_main_alive() == FALSE) return FALSE; } while (shm->mainpid == 0) { if (check_main_alive() == FALSE) counter++; if (counter == 1000) { output(0, "Can't find main at %d\n", shm->mainpid); return FALSE; } if (shm->exit_reason != STILL_RUNNING) return FALSE; sleep(1); } } return TRUE; }
static void watchdog(void) { static const char watchdogname[17]="trinity-watchdog"; static unsigned long lastcount = 0; bool watchdog_exit = FALSE; while (shm->ready == FALSE) { usleep(1); if (shm->exit_reason != STILL_RUNNING) return; } output(0, "Watchdog is alive. (pid:%d)\n", watchdog_pid); prctl(PR_SET_NAME, (unsigned long) &watchdogname); (void)signal(SIGSEGV, SIG_DFL); while (watchdog_exit == FALSE) { int ret = 0; unsigned int i; if (shm_is_corrupt() == TRUE) goto corrupt; if (check_main_alive() == FALSE) goto main_dead; reap_dead_kids(); check_all_locks(); if (syscalls_todo && (shm->stats.total_syscalls_done >= syscalls_todo)) { output(0, "Reached limit %d. Telling children to exit.\n", syscalls_todo); panic(EXIT_REACHED_COUNT); } for_each_child(i) { struct childdata *child = shm->children[i]; struct syscallrecord *rec = &child->syscall; check_child_progress(child); if (rec->op_nr > hiscore) hiscore = rec->op_nr; } if (shm->stats.total_syscalls_done > 1) { if (shm->stats.total_syscalls_done - lastcount > 10000) { output(0, "%ld iterations. [F:%ld S:%ld HI:%ld]\n", shm->stats.total_syscalls_done, shm->stats.failures, shm->stats.successes, hiscore); lastcount = shm->stats.total_syscalls_done; } } /* Only check taint if the mask allows it */ if (kernel_taint_mask != 0) { ret = check_tainted(); if (((ret & kernel_taint_mask) & (~kernel_taint_initial)) != 0) tainted_postmortem(ret); } main_dead: /* Are we done ? */ if (shm->exit_reason != STILL_RUNNING) { /* Give children a chance to exit. */ sleep(1); /* Are there still children running ? */ if (pidmap_empty() == TRUE) watchdog_exit = TRUE; else { static unsigned int last = 0; if (last != shm->running_childs) { last = shm->running_childs; output(0, "exit_reason=%d, but %d children still running.\n", shm->exit_reason, shm->running_childs); } kill_all_kids(); } } sleep(1); } corrupt: kill_all_kids(); }
static void watchdog(void) { static const char watchdogname[17]="trinity-watchdog"; static unsigned long lastcount = 0; bool watchdog_exit = FALSE; int ret = 0; while (shm->ready == FALSE) { sleep(1); if (shm->exit_reason != STILL_RUNNING) return; } output(0, "Watchdog is alive. (pid:%d)\n", watchdog_pid); prctl(PR_SET_NAME, (unsigned long) &watchdogname); (void)signal(SIGSEGV, SIG_DFL); while (watchdog_exit == FALSE) { if (check_shm_sanity() == SHM_CORRUPT) goto corrupt; if (check_main_alive() == FALSE) goto main_dead; if (shm->regenerating == FALSE) { unsigned int i; reap_dead_kids(); check_children(); if (syscalls_todo && (shm->total_syscalls_done >= syscalls_todo)) { output(0, "Reached limit %d. Telling children to exit.\n", syscalls_todo); shm->exit_reason = EXIT_REACHED_COUNT; } // Periodic log syncing. FIXME: This is kinda ugly, and mostly unnecessary. if (shm->total_syscalls_done % 1000 == 0) synclogs(); for_each_pidslot(i) { if (shm->child_syscall_count[i] > hiscore) hiscore = shm->child_syscall_count[i]; } if (shm->total_syscalls_done > 1) { if (shm->total_syscalls_done - lastcount > 10000) { output(0, "%ld iterations. [F:%ld S:%ld HI:%ld]\n", shm->total_syscalls_done, shm->failures, shm->successes, hiscore); lastcount = shm->total_syscalls_done; } } } /* Only check taint if it mask allows it */ if (kernel_taint_mask != 0) { ret = check_tainted(); if (((ret & kernel_taint_mask) & (~kernel_taint_initial)) != 0) { gettimeofday(&shm->taint_tv, NULL); output(0, "kernel became tainted! (%d/%d) Last seed was %u\n", ret, kernel_taint_initial, shm->seed); shm->exit_reason = EXIT_KERNEL_TAINTED; } } main_dead: /* Are we done ? */ if (shm->exit_reason != STILL_RUNNING) { /* Give children a chance to exit. */ sleep(1); /* Are there still children running ? */ if (pidmap_empty() == TRUE) watchdog_exit = TRUE; else { output(0, "exit_reason=%d, but %d children still running.\n", shm->exit_reason, shm->running_childs); kill_all_kids(); } } sleep(1); }
static void watchdog(void) { static unsigned long lastcount = 0; bool watchdog_exit = FALSE; while (watchdog_exit == FALSE) { int ret = 0; unsigned int i; unsigned int stall_count = 0; if (shm_is_corrupt() == TRUE) goto corrupt; if (check_main_alive() == FALSE) goto main_dead; reap_dead_kids(); check_all_locks(); if (syscalls_todo && (shm->stats.total_syscalls_done >= syscalls_todo)) { output(0, "Reached limit %d. Telling children to exit.\n", syscalls_todo); panic(EXIT_REACHED_COUNT); } for_each_child(i) { struct childdata *child = shm->children[i]; struct syscallrecord *rec = &child->syscall; if (is_child_making_progress(child) == FALSE) stall_count++; if (rec->op_nr > hiscore) hiscore = rec->op_nr; } if (stall_count == shm->running_childs) stall_genocide(); if (shm->stats.total_syscalls_done > 1) { if (shm->stats.total_syscalls_done - lastcount > 10000) { char stalltxt[]=" STALLED:XXXX"; if (stall_count > 0) sprintf(stalltxt, " STALLED:%u", stall_count); output(0, "%ld iterations. [F:%ld S:%ld HI:%ld%s]\n", shm->stats.total_syscalls_done, shm->stats.failures, shm->stats.successes, hiscore, stall_count ? stalltxt : ""); lastcount = shm->stats.total_syscalls_done; } } /* Only check taint if the mask allows it */ if (kernel_taint_mask != 0) { ret = check_tainted(); if (((ret & kernel_taint_mask) & (~kernel_taint_initial)) != 0) tainted_postmortem(ret); } main_dead: /* Are we done ? */ if (shm->exit_reason != STILL_RUNNING) { /* Give children a chance to exit. */ sleep(1); /* Are there still children running ? */ if (pidmap_empty() == TRUE) watchdog_exit = TRUE; else { static unsigned int last = 0; if (last != shm->running_childs) { last = shm->running_childs; output(0, "exit_reason=%d, but %d children still running.\n", shm->exit_reason, shm->running_childs); } kill_all_kids(); } } sleep(1); } corrupt: kill_all_kids(); }