diff options
author | Robert Swiecki <robert@swiecki.net> | 2019-02-15 01:56:55 +0100 |
---|---|---|
committer | Robert Swiecki <robert@swiecki.net> | 2019-02-15 01:56:55 +0100 |
commit | 66fc573be82884d7c274362ede1c97909e197c7b (patch) | |
tree | 133cc5dbe77cee275f29aac79ae326c1fbefdf4b | |
parent | 387b79af93e06a8e85597a99209735e22f0aa02e (diff) | |
download | honggfuzz-66fc573be82884d7c274362ede1c97909e197c7b.tar.gz |
posix: check wait events in a loop
-rw-r--r-- | honggfuzz.c | 10 | ||||
-rw-r--r-- | posix/arch.c | 84 |
2 files changed, 54 insertions, 40 deletions
diff --git a/honggfuzz.c b/honggfuzz.c index 4ecf345c..eb8eaa47 100644 --- a/honggfuzz.c +++ b/honggfuzz.c @@ -197,7 +197,7 @@ static void printSummary(honggfuzz_t* hfuzz) { static void pingThreads(honggfuzz_t* hfuzz) { for (size_t i = 0; i < hfuzz->threads.threadsMax; i++) { - if (pthread_kill(hfuzz->threads.threads[i], SIGUSR1) != 0) { + if (pthread_kill(hfuzz->threads.threads[i], SIGUSR1) != 0 && errno != EINTR) { PLOG_W("pthread_kill(thread=%zu, SIGUSR1)", i); } } @@ -215,13 +215,15 @@ static void* signalThread(void* arg) { for (;;) { int sig; - if (sigwait(&ss, &sig) != 0) { + if (sigwait(&ss, &sig) != 0 && errno != EINTR) { PLOG_F("sigwait(SIGCHLD)"); } if (fuzz_isTerminating()) { break; } - pingThreads(hfuzz); + if (sig == SIGCHLD) { + pingThreads(hfuzz); + } } return NULL; @@ -321,11 +323,11 @@ int main(int argc, char** argv) { fuzz_setTerminating(); - /* Ping threads one last time */ void* retval; if (pthread_join(sigthread, &retval) != 0) { PLOG_W("Couldn't stop the signal thread"); } + /* Ping threads one last time */ pingThreads(&hfuzz); fuzz_threadsStop(&hfuzz); diff --git a/posix/arch.c b/posix/arch.c index 2aafac29..cdc14293 100644 --- a/posix/arch.c +++ b/posix/arch.c @@ -80,12 +80,12 @@ struct { * Returns true if a process exited (so, presumably, we can delete an input * file) */ -static bool arch_analyzeSignal(run_t* run, int status) { +static void arch_analyzeSignal(run_t* run, int status) { /* * Resumed by delivery of SIGCONT */ if (WIFCONTINUED(status)) { - return false; + return; } /* @@ -93,7 +93,7 @@ static bool arch_analyzeSignal(run_t* run, int status) { */ if (WIFEXITED(status)) { LOG_D("Process (pid %d) exited normally with status %d", run->pid, WEXITSTATUS(status)); - return true; + return; } /* @@ -102,14 +102,14 @@ static bool arch_analyzeSignal(run_t* run, int status) { if (!WIFSIGNALED(status)) { LOG_E("Process (pid %d) exited with the following status %d, please report that as a bug", run->pid, status); - return false; + return; } int termsig = WTERMSIG(status); LOG_D("Process (pid %d) killed by signal %d '%s'", run->pid, termsig, strsignal(termsig)); if (!arch_sigs[termsig].important) { LOG_D("It's not that important signal, skipping"); - return true; + return; } char localtmstr[PATH_MAX]; @@ -137,8 +137,6 @@ static bool arch_analyzeSignal(run_t* run, int status) { newname, run->dynamicFile, run->dynamicFileSz, O_CREAT | O_EXCL | O_WRONLY) == false) { LOG_E("Couldn't save crash to '%s'", run->crashFileName); } - - return true; } pid_t arch_fork(run_t* fuzzer HF_ATTR_UNUSED) { @@ -186,6 +184,48 @@ void arch_prepareParent(run_t* fuzzer HF_ATTR_UNUSED) { void arch_prepareParentAfterFork(run_t* fuzzer HF_ATTR_UNUSED) { } +static bool arch_checkWait(run_t* run) { + /* All queued wait events must be tested when SIGCHLD was delivered */ + for (;;) { + int status; + int wflags = WNOHANG; +#if defined(__WNOTHREAD) + wflags |= __WNOTHREAD; +#endif /* defined(__WNOTHREAD) */ +#if defined(__WALL) + wflags |= __WALL; +#endif /* defined(__WALL) */ + + pid_t pid = TEMP_FAILURE_RETRY(waitpid(run->pid, &status, wflags)); + if (pid == 0) { + return false; + } + if (pid == -1 && errno == ECHILD) { + LOG_D("No more processes to track"); + return true; + } + if (pid == -1) { + PLOG_F("waitpid() failed"); + } + + char statusStr[4096]; + LOG_D("pid=%d returned with status: %s", pid, + subproc_StatusToStr(status, statusStr, sizeof(statusStr))); + + arch_analyzeSignal(run, status); + + if (pid == run->pid && (WIFEXITED(status) || WIFSIGNALED(status))) { + if (run->global->exe.persistent) { + if (!fuzz_isTerminating()) { + LOG_W("Persistent mode: pid=%d exited with status: %s", (int)run->pid, + subproc_StatusToStr(status, statusStr, sizeof(statusStr))); + } + } + return true; + } + } +} + void arch_reapChild(run_t* run) { for (;;) { if (subproc_persistentModeStateMachine(run)) { @@ -216,35 +256,7 @@ void arch_reapChild(run_t* run) { } } - int status; - int ret = waitpid(run->pid, &status, WNOHANG); - if (ret == 0) { - continue; - } - if (ret == -1 && errno == EINTR) { - continue; - } - if (ret == -1) { - PLOG_W("waitpid(pid=%d)", run->pid); - continue; - } - if (ret != run->pid) { - continue; - } - - char strStatus[4096]; - if (run->global->exe.persistent && ret == run->pid && - (WIFEXITED(status) || WIFSIGNALED(status))) { - if (!fuzz_isTerminating()) { - LOG_W("Persistent mode: PID %d exited with status: %s", ret, - subproc_StatusToStr(status, strStatus, sizeof(strStatus))); - } - } - - LOG_D("Process (pid %d) came back with status: %s", run->pid, - subproc_StatusToStr(status, strStatus, sizeof(strStatus))); - - if (arch_analyzeSignal(run, status)) { + if (arch_checkWait(run)) { run->pid = 0; break; } |