summaryrefslogtreecommitdiff
path: root/mac/arch.c
diff options
context:
space:
mode:
Diffstat (limited to 'mac/arch.c')
-rw-r--r--mac/arch.c107
1 files changed, 53 insertions, 54 deletions
diff --git a/mac/arch.c b/mac/arch.c
index e0d0ca2e..d641cea8 100644
--- a/mac/arch.c
+++ b/mac/arch.c
@@ -24,11 +24,19 @@
#include "arch.h"
+#import <Foundation/Foundation.h>
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
+#include <mach/i386/thread_status.h>
+#include <mach/mach.h>
+#include <mach/mach_types.h>
+#include <mach/mach_vm.h>
+#include <mach/task_info.h>
#include <poll.h>
+#include <pthread.h>
+#include <servers/bootstrap.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -49,20 +57,9 @@
#include "libhfcommon/files.h"
#include "libhfcommon/log.h"
#include "libhfcommon/util.h"
-#include "subproc.h"
-
-#include <mach/i386/thread_status.h>
-#include <mach/mach.h>
-#include <mach/mach_types.h>
-#include <mach/mach_vm.h>
-#include <mach/task_info.h>
-#include <pthread.h>
-#include <servers/bootstrap.h>
-
#include "mach_exc.h"
#include "mach_excServer.h"
-
-#import <Foundation/Foundation.h>
+#include "subproc.h"
/*
* Interface to third_party/CrashReport_*.o
@@ -182,12 +179,12 @@ static void arch_generateReport(run_t* run, int termsig) {
* 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;
}
/*
@@ -195,7 +192,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;
}
/*
@@ -204,14 +201,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 true;
+ 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;
}
/*
@@ -245,7 +242,7 @@ static bool arch_analyzeSignal(run_t* run, int status) {
run->backtrace) != -1)) {
LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", run->backtrace);
ATOMIC_POST_INC(run->global->cnts.blCrashesCnt);
- return true;
+ return;
}
/* If dry run mode, copy file with same name into workspace */
@@ -271,13 +268,13 @@ static bool arch_analyzeSignal(run_t* run, int status) {
LOG_I("Crash (dup): '%s' already exists, skipping", run->crashFileName);
// Clear filename so that verifier can understand we hit a duplicate
memset(run->crashFileName, 0, sizeof(run->crashFileName));
- return true;
+ return;
}
if (!files_writeBufToFile(run->crashFileName, run->dynamicFile, run->dynamicFileSz,
O_CREAT | O_EXCL | O_WRONLY)) {
LOG_E("Couldn't save crash as '%s'", run->crashFileName);
- return true;
+ return;
}
LOG_I("Crash: saved as '%s'", run->crashFileName);
@@ -287,8 +284,6 @@ static bool arch_analyzeSignal(run_t* run, int status) {
ATOMIC_CLEAR(run->global->cfg.dynFileIterExpire);
arch_generateReport(run, termsig);
-
- return true;
}
pid_t arch_fork(run_t* run HF_ATTR_UNUSED) {
@@ -362,6 +357,41 @@ void arch_prepareParent(run_t* run HF_ATTR_UNUSED) {
void arch_prepareParentAfterFork(run_t* run HF_ATTR_UNUSED) {
}
+static bool arch_checkWait(run_t* run) {
+ /* All queued wait events must be tested when SIGCHLD was delivered */
+ for (;;) {
+ int status;
+ /* Wait for the whole process group of run->pid */
+ pid_t pid = TEMP_FAILURE_RETRY(wait4(-(run->pid), &status, WNOHANG, NULL));
+ if (pid == 0) {
+ return false;
+ }
+ if (pid == -1 && errno == ECHILD) {
+ LOG_D("No more processes to track");
+ return true;
+ }
+ if (pid == -1) {
+ PLOG_F("wait4(pid/session=%d) failed", (int)run->pid);
+ }
+
+ arch_analyzeSignal(run, status);
+
+ char statusStr[4096];
+ LOG_D("pid=%d returned with status: %s", pid,
+ subproc_StatusToStr(status, statusStr, sizeof(statusStr)));
+
+ 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", pid,
+ subproc_StatusToStr(status, statusStr, sizeof(statusStr)));
+ }
+ }
+ return true;
+ }
+ }
+}
+
void arch_reapChild(run_t* run) {
for (;;) {
if (subproc_persistentModeStateMachine(run)) {
@@ -390,38 +420,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 && errno == ECHILD) {
- run->pid = 0;
- break;
- }
- if (ret == -1) {
- PLOG_W("waitpid(pid=%d)", run->pid);
- continue;
- }
- if (ret != run->pid) {
- continue;
- }
-
- char strStatus[4096];
- if (run->global->exe.persistent && (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;
}