]> git.cworth.org Git - apitrace/blobdiff - common/trace_writer_local.cpp
Remove FunctionSig::backtrace member.
[apitrace] / common / trace_writer_local.cpp
index f50dd21cade4bfe0c49e218904bfb5a424e6f73c..866170139c2a45356b3abcef67e482cf3c426b32 100644 (file)
 #include <string.h>
 
 #include "os.hpp"
+#include "os_thread.hpp"
+#include "os_string.hpp"
 #include "trace_file.hpp"
-#include "trace_writer.hpp"
+#include "trace_writer_local.hpp"
 #include "trace_format.hpp"
+#include "trace_backtrace.hpp"
 
 
 namespace trace {
@@ -73,32 +76,36 @@ LocalWriter::~LocalWriter()
 
 void
 LocalWriter::open(void) {
-    os::Path szFileName;
+    os::String szFileName;
 
-    char *lpFileName;
+    const char *lpFileName;
 
-    lpFileName = const_cast<char *>(getenv("TRACE_FILE"));
+    lpFileName = getenv("TRACE_FILE");
     if (!lpFileName) {
-        lpFileName = szFileName.buf(PATH_MAX);
         static unsigned dwCounter = 0;
 
-        os::Path process = os::getProcessName();
+        os::String process = os::getProcessName();
 #ifdef _WIN32
         process.trimExtension();
 #endif
         process.trimDirectory();
 
-        os::Path prefix = os::getCurrentDir();
+#ifdef ANDROID
+       os::String prefix = "/data";
+#else
+       os::String prefix = os::getCurrentDir();
+#endif
         prefix.join(process);
 
         for (;;) {
             FILE *file;
 
             if (dwCounter)
-                snprintf(lpFileName, PATH_MAX, "%s.%u.trace", prefix.str(), dwCounter);
+                szFileName = os::String::format("%s.%u.trace", prefix.str(), dwCounter);
             else
-                snprintf(lpFileName, PATH_MAX, "%s.trace", prefix.str());
+                szFileName = os::String::format("%s.trace", prefix.str());
 
+            lpFileName = szFileName;
             file = fopen(lpFileName, "rb");
             if (file == NULL)
                 break;
@@ -111,7 +118,10 @@ LocalWriter::open(void) {
 
     os::log("apitrace: tracing to %s\n", lpFileName);
 
-    Writer::open(lpFileName);
+    if (!Writer::open(lpFileName)) {
+        os::log("apitrace: error: failed to open %s\n", lpFileName);
+        os::abort();
+    }
 
 #if 0
     // For debugging the exception handler
@@ -119,25 +129,47 @@ LocalWriter::open(void) {
 #endif
 }
 
-unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
-    os::acquireMutex();
+static uintptr_t next_thread_num = 1;
+
+static OS_THREAD_SPECIFIC_PTR(void)
+thread_num;
+
+unsigned LocalWriter::beginEnter(const FunctionSig *sig, bool fake) {
+    mutex.lock();
     ++acquired;
 
     if (!m_file->isOpened()) {
         open();
     }
 
-    return Writer::beginEnter(sig);
+    // Although thread_num is a void *, we actually use it as a uintptr_t
+    uintptr_t this_thread_num =
+        reinterpret_cast<uintptr_t>(static_cast<void *>(thread_num));
+    if (!this_thread_num) {
+        this_thread_num = next_thread_num++;
+        thread_num = reinterpret_cast<void *>(this_thread_num);
+    }
+
+    assert(this_thread_num);
+    unsigned thread_id = this_thread_num - 1;
+    unsigned call_no = Writer::beginEnter(sig, thread_id);
+    if (!fake) {
+        std::vector<RawStackFrame> backtrace = get_backtrace();
+        beginBacktrace();
+        writeBacktrace(backtrace);
+        endBacktrace();
+    }
+    return call_no;
 }
 
 void LocalWriter::endEnter(void) {
     Writer::endEnter();
     --acquired;
-    os::releaseMutex();
+    mutex.unlock();
 }
 
 void LocalWriter::beginLeave(unsigned call) {
-    os::acquireMutex();
+    mutex.lock();
     ++acquired;
     Writer::beginLeave(call);
 }
@@ -145,23 +177,28 @@ void LocalWriter::beginLeave(unsigned call) {
 void LocalWriter::endLeave(void) {
     Writer::endLeave();
     --acquired;
-    os::releaseMutex();
+    mutex.unlock();
 }
 
 void LocalWriter::flush(void) {
     /*
      * Do nothing if the mutex is already acquired (e.g., if a segfault happen
-     * while writing the file) to prevent dead-lock.
+     * while writing the file) as state could be inconsistent, therefore yield
+     * inconsistent trace files and/or repeated segfaults till infinity.
      */
 
-    if (!acquired) {
-        os::acquireMutex();
+    mutex.lock();
+    if (acquired) {
+        os::log("apitrace: ignoring exception while tracing\n");
+    } else {
+        ++acquired;
         if (m_file->isOpened()) {
             os::log("apitrace: flushing trace due to an exception\n");
             m_file->flush();
         }
-        os::releaseMutex();
+        --acquired;
     }
+    mutex.unlock();
 }