]> git.cworth.org Git - apitrace/blobdiff - os_posix.cpp
Various changes to the flushing code.
[apitrace] / os_posix.cpp
index 3f54da2c9545fc516f1153427b5583ac47bb646a..684ffac40f668dd4398a77e60688c561c9d73791 100644 (file)
@@ -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,7 @@
  *
  **************************************************************************/
 
+
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <sys/time.h>
 #include <pthread.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
 
 #include "os.hpp"
 
+
 namespace OS {
 
 
@@ -57,16 +66,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 +117,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 +138,71 @@ Abort(void)
 }
 
 
+struct Interrupts
+{
+    Interrupts()
+        : set(false),
+          sig_int(NULL),
+          sig_hup(NULL),
+          sig_term(NULL)
+    {}
+
+    bool set;
+    void (*sig_int)(int);
+    void (*sig_hup)(int);
+    void (*sig_term)(int);
+
+    void (*handler)(int);
+};
+static Interrupts interrupts;
+
+static void InterruptHandler(int sig)
+{
+    if (interrupts.set && interrupts.handler) {
+        interrupts.handler(sig);
+    }
+    if (sig == SIGINT) {
+        if (!interrupts.sig_int)
+            exit(sig);
+        interrupts.sig_int(sig);
+    } else if (sig == SIGHUP) {
+        if (!interrupts.sig_hup)
+            exit(sig);
+        interrupts.sig_hup(sig);
+    } else if (sig == SIGTERM) {
+        if (!interrupts.sig_term)
+            exit(sig);
+        interrupts.sig_term(sig);
+    }
+}
+
+void
+CatchInterrupts(void (*func)(int))
+{
+    interrupts.handler = func;
+
+    if (!interrupts.set) {
+        struct sigaction new_action, old_action;
+        new_action.sa_handler = InterruptHandler;
+        sigemptyset(&new_action.sa_mask);
+        new_action.sa_flags = 0;
+#define SET_IF_NOT_IGNORED(sig, old_handler)            \
+        do {                                            \
+            sigaction(sig, NULL, &old_action);          \
+            if (old_action.sa_handler != SIG_IGN) {     \
+                old_handler = old_action.sa_handler;    \
+                sigaction(sig, &new_action, NULL);      \
+            }                                           \
+        } while (0)
+
+        SET_IF_NOT_IGNORED(SIGINT, interrupts.sig_int);
+        SET_IF_NOT_IGNORED(SIGHUP, interrupts.sig_hup);
+        SET_IF_NOT_IGNORED(SIGTERM, interrupts.sig_term);
+
+        interrupts.set = true;
+#undef SET_IF_NOT_IGNORED
+    }
+}
+
 } /* namespace OS */