X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=common%2Fos_posix.cpp;h=0d93b31bcafa6e56604fa639a7656d20128835ca;hb=b3381e6a8fcad8fc1e3ddd816eac127b0e254850;hp=65c5404e3c0e64dd92c2184143474e05fe815b10;hpb=0e47f66f21683a18f34282e07efa85cdac4fe0e0;p=apitrace diff --git a/common/os_posix.cpp b/common/os_posix.cpp index 65c5404..0d93b31 100644 --- a/common/os_posix.cpp +++ b/common/os_posix.cpp @@ -30,7 +30,6 @@ #include #include -#include #include #include #include @@ -45,6 +44,10 @@ #include #endif +#ifdef ANDROID +#include +#endif + #ifndef PATH_MAX #warning PATH_MAX undefined #define PATH_MAX 4096 @@ -131,7 +134,11 @@ int execute(char * const * args) if (pid == 0) { // child execvp(args[0], args); - fprintf(stderr, "error: failed to execute %s\n", args[0]); + fprintf(stderr, "error: failed to execute:"); + for (unsigned i = 0; args[i]; ++i) { + fprintf(stderr, " %s", args[i]); + } + fprintf(stderr, "\n"); exit(-1); } else { // parent @@ -140,28 +147,41 @@ int execute(char * const * args) return -1; } int status = -1; + int ret; waitpid(pid, &status, 0); - return status; + if (WIFEXITED(status)) { + ret = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + // match shell return code + ret = WTERMSIG(status) + 128; + } else { + ret = 128; + } + return ret; } } +static volatile bool logging = false; + void log(const char *format, ...) { + logging = true; va_list ap; va_start(ap, format); fflush(stdout); +#ifdef ANDROID + __android_log_vprint(ANDROID_LOG_DEBUG, "apitrace", format, ap); +#else vfprintf(stderr, format, ap); +#endif va_end(ap); + logging = false; } -long long -getTime(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_usec + tv.tv_sec*1000000LL; -} +#if defined(__APPLE__) +long long timeFrequency = 0LL; +#endif void abort(void) @@ -185,12 +205,22 @@ struct sigaction old_actions[NUM_SIGNALS]; static void signalHandler(int sig, siginfo_t *info, void *context) { + /* + * There are several signals that can happen when logging to stdout/stderr. + * For example, SIGPIPE will be emitted if stderr is a pipe with no + * readers. Therefore ignore any signal while logging by returning + * immediately, to prevent deadlocks. + */ + if (logging) { + return; + } + static int recursion_count = 0; - fprintf(stderr, "apitrace: warning: caught signal %i\n", sig); + log("apitrace: warning: caught signal %i\n", sig); if (recursion_count) { - fprintf(stderr, "apitrace: warning: recursion handling signal %i\n", sig); + log("apitrace: warning: recursion handling signal %i\n", sig); } else { if (gCallback) { ++recursion_count; @@ -202,7 +232,7 @@ signalHandler(int sig, siginfo_t *info, void *context) struct sigaction *old_action; if (sig >= NUM_SIGNALS) { /* This should never happen */ - fprintf(stderr, "error: unexpected signal %i\n", sig); + log("error: unexpected signal %i\n", sig); raise(SIGKILL); } old_action = &old_actions[sig]; @@ -212,7 +242,7 @@ signalHandler(int sig, siginfo_t *info, void *context) old_action->sa_sigaction(sig, info, context); } else { if (old_action->sa_handler == SIG_DFL) { - fprintf(stderr, "apitrace: info: taking default action for signal %i\n", sig); + log("apitrace: info: taking default action for signal %i\n", sig); #if 1 struct sigaction dfl_action; @@ -248,11 +278,26 @@ setExceptionCallback(void (*callback)(void)) for (int sig = 1; sig < NUM_SIGNALS; ++sig) { - // SIGKILL and SIGSTOP can't be handled - if (sig != SIGKILL && sig != SIGSTOP) { - if (sigaction(sig, NULL, &old_actions[sig]) >= 0) { - sigaction(sig, &new_action, NULL); - } + // SIGKILL and SIGSTOP can't be handled. + if (sig == SIGKILL || sig == SIGSTOP) { + continue; + } + + /* + * SIGPIPE can be emitted when writing to stderr that is redirected + * to a pipe without readers. It is also very unlikely to ocurr + * inside graphics APIs, and most applications where it can occur + * normally already ignore it. In summary, it is unlikely that a + * SIGPIPE will cause abnormal termination, which it is likely that + * intercepting here will cause problems, so simple don't intercept + * it here. + */ + if (sig == SIGPIPE) { + continue; + } + + if (sigaction(sig, NULL, &old_actions[sig]) >= 0) { + sigaction(sig, &new_action, NULL); } } }