X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=os_posix.cpp;h=991ad0e7cabef3162162fd19176e2d0b6580c9d6;hb=ebf971eec6c3a5f98885cc418e04690ba213b645;hp=3f54da2c9545fc516f1153427b5583ac47bb646a;hpb=df66a909dbd545cac08776da18b166ab847c08e9;p=apitrace diff --git a/os_posix.cpp b/os_posix.cpp index 3f54da2..991ad0e 100644 --- a/os_posix.cpp +++ b/os_posix.cpp @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2010 VMware, Inc. + * Copyright 2010-2011 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -23,6 +23,8 @@ * **************************************************************************/ + +#include #include #include #include @@ -30,9 +32,17 @@ #include #include #include +#include +#include +#include + +#ifdef __APPLE__ +#include +#endif #include "os.hpp" + namespace OS { @@ -57,16 +67,33 @@ ReleaseMutex(void) bool GetProcessName(char *str, size_t size) { - ssize_t len; char szProcessPath[PATH_MAX + 1]; char *lpProcessName; - + // http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe - len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1); - if (len == -1) { +#ifdef __APPLE__ + uint32_t len = sizeof szProcessPath; + if (_NSGetExecutablePath(szProcessPath, &len) != 0) { *str = 0; return false; } +#else + ssize_t len; + len = readlink("/proc/self/exe", szProcessPath, sizeof(szProcessPath) - 1); + if (len == -1) { + // /proc/self/exe is not available on setuid processes, so fallback to + // /proc/self/cmdline. + int fd = open("/proc/self/cmdline", O_RDONLY); + if (fd >= 0) { + len = read(fd, szProcessPath, sizeof(szProcessPath) - 1); + close(fd); + } + } + if (len <= 0) { + snprintf(str, size, "%i", (int)getpid()); + return true; + } +#endif szProcessPath[len] = 0; lpProcessName = strrchr(szProcessPath, '/'); @@ -91,18 +118,18 @@ GetCurrentDir(char *str, size_t size) void DebugMessage(const char *format, ...) { - va_list ap; - va_start(ap, format); - fflush(stdout); - vfprintf(stderr, format, ap); - va_end(ap); + va_list ap; + va_start(ap, format); + fflush(stdout); + vfprintf(stderr, format, ap); + va_end(ap); } long long GetTime(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_usec + tv.tv_sec*1000000LL; + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_usec + tv.tv_sec*1000000LL; } void @@ -112,5 +139,92 @@ Abort(void) } +static void (*gCallback)(void) = NULL; + +#define NUM_SIGNALS 16 + +struct sigaction old_actions[NUM_SIGNALS]; + +static void signal_handler(int sig, siginfo_t *info, void *context) +{ + static int recursion_count = 0; + + fprintf(stderr, "signal_handler: sig = %i\n", sig); + + if (recursion_count) { + fprintf(stderr, "recursion with sig %i\n", sig); + } else { + if (gCallback) { + ++recursion_count; + gCallback(); + --recursion_count; + } + } + + struct sigaction *old_action; + if (sig >= NUM_SIGNALS) { + /* This should never happen */ + fprintf(stderr, "Unexpected signal %i\n", sig); + raise(SIGKILL); + } + old_action = &old_actions[sig]; + + if (old_action->sa_flags & SA_SIGINFO) { + // Handler is in sa_sigaction + old_action->sa_sigaction(sig, info, context); + } else { + if (old_action->sa_handler == SIG_DFL) { + fprintf(stderr, "taking default action for signal %i\n", sig); + +#if 1 + struct sigaction dfl_action; + dfl_action.sa_handler = SIG_DFL; + sigemptyset (&dfl_action.sa_mask); + dfl_action.sa_flags = 0; + sigaction(sig, &dfl_action, NULL); + + raise(sig); +#else + raise(SIGKILL); +#endif + } else if (old_action->sa_handler == SIG_IGN) { + /* ignore */ + } else { + /* dispatch to handler */ + old_action->sa_handler(sig); + } + } +} + +void +SetExceptionCallback(void (*callback)(void)) +{ + assert(!gCallback); + if (!gCallback) { + gCallback = callback; + + struct sigaction new_action; + new_action.sa_sigaction = signal_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = SA_SIGINFO | SA_RESTART; + + + 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); + } + } + } + } +} + +void +ResetExceptionCallback(void) +{ + gCallback = NULL; +} + } /* namespace OS */