]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'master' into compression
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 24 Aug 2011 18:58:47 +0000 (19:58 +0100)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Wed, 24 Aug 2011 18:58:47 +0000 (19:58 +0100)
Conflicts:
os.hpp
os_posix.cpp
os_win32.cpp
trace_writer.cpp

12 files changed:
CMakeLists.txt
d3d8.py
d3d9.py
gltrace.py
os.hpp
os_posix.cpp
os_win32.cpp
trace.py
trace_file.cpp
trace_local_writer.cpp [new file with mode: 0644]
trace_writer.cpp
trace_writer.hpp

index 67d327a6c6a32d02d110f7115cb7f5e923f5b3ee..39ffde57885c1a5886445d7d6c976d467d292255 100755 (executable)
@@ -184,6 +184,7 @@ add_library (common
     trace_model.cpp
     trace_parser.cpp
     trace_writer.cpp
+    trace_local_writer.cpp
     trace_model_writer.cpp
     image.cpp
     image_bmp.cpp
diff --git a/d3d8.py b/d3d8.py
index f5fb76ea917763c36c5c2ce3f4e9f8fe05b17807..f579a9b40617733f19d243d6532bc8e73a759cd0 100644 (file)
--- a/d3d8.py
+++ b/d3d8.py
@@ -288,7 +288,7 @@ class D3D8Tracer(DllTracer):
     def dump_arg_instance(self, function, arg):
         # Dump shaders as strings
         if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction':
-            print '    DumpShader(__writer, %s);' % (arg.name)
+            print '    DumpShader(Trace::localWriter, %s);' % (arg.name)
             return
 
         DllTracer.dump_arg_instance(self, function, arg)
diff --git a/d3d9.py b/d3d9.py
index a63b805e11916ddc371d56ac86c4dd8319b23c4c..640d218dc7a8c2b4726d142cd268e6ec92e128ca 100644 (file)
--- a/d3d9.py
+++ b/d3d9.py
@@ -455,7 +455,7 @@ class D3D9Tracer(DllTracer):
     def dump_arg_instance(self, function, arg):
         # Dump shaders as strings
         if function.name in ('CreateVertexShader', 'CreatePixelShader') and arg.name == 'pFunction':
-            print '    DumpShader(__writer, %s);' % (arg.name)
+            print '    DumpShader(Trace::localWriter, %s);' % (arg.name)
             return
 
         DllTracer.dump_arg_instance(self, function, arg)
index af5714242e5a7a148a1befc4d928bd929000405b..9224bbeb4ba15b0048dcba8a7181721f958acd8a 100644 (file)
@@ -412,13 +412,13 @@ class GlTracer(Tracer):
                     # Emit a fake function
                     print '        {'
                     print '            static const Trace::FunctionSig &__sig = %s ? __glEnableClientState_sig : __glDisableClientState_sig;' % flag_name
-                    print '            unsigned __call = __writer.beginEnter(&__sig);'
-                    print '            __writer.beginArg(0);'
+                    print '            unsigned __call = Trace::localWriter.beginEnter(&__sig);'
+                    print '            Trace::localWriter.beginArg(0);'
                     dump_instance(glapi.GLenum, enable_name)
-                    print '            __writer.endArg();'
-                    print '            __writer.endEnter();'
-                    print '            __writer.beginLeave(__call);'
-                    print '            __writer.endLeave();'
+                    print '            Trace::localWriter.endArg();'
+                    print '            Trace::localWriter.endEnter();'
+                    print '            Trace::localWriter.beginLeave(__call);'
+                    print '            Trace::localWriter.endLeave();'
                     print '        }'
 
             print '        return;'
@@ -523,19 +523,19 @@ class GlTracer(Tracer):
         Tracer.dispatch_function(self, function)
 
     def emit_memcpy(self, dest, src, length):
-        print '        unsigned __call = __writer.beginEnter(&__memcpy_sig);'
-        print '        __writer.beginArg(0);'
-        print '        __writer.writeOpaque(%s);' % dest
-        print '        __writer.endArg();'
-        print '        __writer.beginArg(1);'
-        print '        __writer.writeBlob(%s, %s);' % (src, length)
-        print '        __writer.endArg();'
-        print '        __writer.beginArg(2);'
-        print '        __writer.writeUInt(%s);' % length
-        print '        __writer.endArg();'
-        print '        __writer.endEnter();'
-        print '        __writer.beginLeave(__call);'
-        print '        __writer.endLeave();'
+        print '        unsigned __call = Trace::localWriter.beginEnter(&__memcpy_sig);'
+        print '        Trace::localWriter.beginArg(0);'
+        print '        Trace::localWriter.writeOpaque(%s);' % dest
+        print '        Trace::localWriter.endArg();'
+        print '        Trace::localWriter.beginArg(1);'
+        print '        Trace::localWriter.writeBlob(%s, %s);' % (src, length)
+        print '        Trace::localWriter.endArg();'
+        print '        Trace::localWriter.beginArg(2);'
+        print '        Trace::localWriter.writeUInt(%s);' % length
+        print '        Trace::localWriter.endArg();'
+        print '        Trace::localWriter.endEnter();'
+        print '        Trace::localWriter.beginLeave(__call);'
+        print '        Trace::localWriter.endLeave();'
        
     buffer_targets = [
         'ARRAY_BUFFER',
@@ -637,15 +637,15 @@ class GlTracer(Tracer):
             print '    __glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &__element_array_buffer);'
             print '    if (!__element_array_buffer) {'
             if isinstance(arg.type, stdapi.Array):
-                print '        __writer.beginArray(%s);' % arg.type.length
+                print '        Trace::localWriter.beginArray(%s);' % arg.type.length
                 print '        for(GLsizei i = 0; i < %s; ++i) {' % arg.type.length
-                print '            __writer.beginElement();'
-                print '            __writer.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
-                print '            __writer.endElement();'
+                print '            Trace::localWriter.beginElement();'
+                print '            Trace::localWriter.writeBlob(%s[i], count[i]*__gl_type_size(type));' % (arg.name)
+                print '            Trace::localWriter.endElement();'
                 print '        }'
-                print '        __writer.endArray();'
+                print '        Trace::localWriter.endArray();'
             else:
-                print '        __writer.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
+                print '        Trace::localWriter.writeBlob(%s, count*__gl_type_size(type));' % (arg.name)
             print '    } else {'
             Tracer.dump_arg_instance(self, function, arg)
             print '    }'
@@ -660,7 +660,7 @@ class GlTracer(Tracer):
             print '        GLint __unpack_buffer = 0;'
             print '        __glGetIntegerv(GL_PIXEL_UNPACK_BUFFER_BINDING, &__unpack_buffer);'
             print '        if (__unpack_buffer) {'
-            print '            __writer.writeOpaque(%s);' % arg.name
+            print '            Trace::localWriter.writeOpaque(%s);' % arg.name
             print '        } else {'
             Tracer.dump_arg_instance(self, function, arg)
             print '        }'
@@ -718,19 +718,19 @@ class GlTracer(Tracer):
 
             # Emit a fake function
             self.array_trace_intermezzo(api, uppercase_name)
-            print '            unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+            print '            unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
             for arg in function.args:
                 assert not arg.output
-                print '            __writer.beginArg(%u);' % (arg.index,)
+                print '            Trace::localWriter.beginArg(%u);' % (arg.index,)
                 if arg.name != 'pointer':
                     dump_instance(arg.type, arg.name)
                 else:
-                    print '            __writer.writeBlob((const void *)%s, __size);' % (arg.name)
-                print '            __writer.endArg();'
+                    print '            Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
+                print '            Trace::localWriter.endArg();'
             
-            print '            __writer.endEnter();'
-            print '            __writer.beginLeave(__call);'
-            print '            __writer.endLeave();'
+            print '            Trace::localWriter.endEnter();'
+            print '            Trace::localWriter.beginLeave(__call);'
+            print '            Trace::localWriter.endLeave();'
             print '        }'
             print '    }'
             self.array_epilog(api, uppercase_name)
@@ -791,19 +791,19 @@ class GlTracer(Tracer):
             print '                    size_t __size = __%s_size(%s, maxindex);' % (function.name, arg_names)
 
             # Emit a fake function
-            print '                    unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+            print '                    unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
             for arg in function.args:
                 assert not arg.output
-                print '                    __writer.beginArg(%u);' % (arg.index,)
+                print '                    Trace::localWriter.beginArg(%u);' % (arg.index,)
                 if arg.name != 'pointer':
                     dump_instance(arg.type, arg.name)
                 else:
-                    print '                    __writer.writeBlob((const void *)%s, __size);' % (arg.name)
-                print '                    __writer.endArg();'
+                    print '                    Trace::localWriter.writeBlob((const void *)%s, __size);' % (arg.name)
+                print '                    Trace::localWriter.endArg();'
             
-            print '                    __writer.endEnter();'
-            print '                    __writer.beginLeave(__call);'
-            print '                    __writer.endLeave();'
+            print '                    Trace::localWriter.endEnter();'
+            print '                    Trace::localWriter.beginLeave(__call);'
+            print '                    Trace::localWriter.endLeave();'
             print '                }'
             print '            }'
             print '        }'
@@ -859,15 +859,15 @@ class GlTracer(Tracer):
         self.fake_call(function, [texture])
 
     def fake_call(self, function, args):
-        print '            unsigned __fake_call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+        print '            unsigned __fake_call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
         for arg, instance in zip(function.args, args):
             assert not arg.output
-            print '            __writer.beginArg(%u);' % (arg.index,)
+            print '            Trace::localWriter.beginArg(%u);' % (arg.index,)
             dump_instance(arg.type, instance)
-            print '            __writer.endArg();'
-        print '            __writer.endEnter();'
-        print '            __writer.beginLeave(__fake_call);'
-        print '            __writer.endLeave();'
+            print '            Trace::localWriter.endArg();'
+        print '            Trace::localWriter.endEnter();'
+        print '            Trace::localWriter.beginLeave(__fake_call);'
+        print '            Trace::localWriter.endLeave();'
 
 
 
diff --git a/os.hpp b/os.hpp
index e93b113fbe8606f2ebea12fc4f425bbecb8ddc8e..8e487b502937f02c5e80ae0a292c9c7fd0e7d7d0 100644 (file)
--- a/os.hpp
+++ b/os.hpp
@@ -90,7 +90,8 @@ long long GetTime(void);
 
 void Abort(void);
 
-void CatchInterrupts(void (*func)(int));
+void SetExceptionCallback(void (*callback)(void));
+void ResetExceptionCallback(void);
 
 } /* namespace OS */
 
index c072d5da7c4361a216d36e669fc652d6464e1c86..991ad0e7cabef3162162fd19176e2d0b6580c9d6 100644 (file)
@@ -24,6 +24,7 @@
  **************************************************************************/
 
 
+#include <assert.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -138,82 +139,92 @@ Abort(void)
 }
 
 
-struct Interrupts
-{
-    Interrupts()
-        : set(false),
-          sig_int(NULL),
-          sig_hup(NULL),
-          sig_term(NULL),
-          sig_segv(NULL),
-          handler(NULL)
-    {}
-
-    bool set;
-    void (*sig_int)(int);
-    void (*sig_hup)(int);
-    void (*sig_term)(int);
-    void (*sig_segv)(int);
-
-    void (*handler)(int);
-};
-static Interrupts interrupts;
-
-static void InterruptHandler(int sig)
+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)
 {
-    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);
+    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;
         }
-        interrupts.sig_term(sig);
-    } else if (sig == SIGSEGV) {
-        if (interrupts.sig_segv) {
-            interrupts.sig_segv(sig);
+    }
+
+    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
-CatchInterrupts(void (*func)(int))
+SetExceptionCallback(void (*callback)(void))
 {
-    interrupts.handler = func;
+    assert(!gCallback);
+    if (!gCallback) {
+        gCallback = callback;
 
-    if (!interrupts.set) {
-        struct sigaction new_action, old_action;
-        new_action.sa_handler = InterruptHandler;
+        struct sigaction new_action;
+        new_action.sa_sigaction = signal_handler;
         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);
-        SET_IF_NOT_IGNORED(SIGSEGV, interrupts.sig_segv);
-
-        interrupts.set = true;
-#undef SET_IF_NOT_IGNORED
+        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 */
 
index a35e2a3c0229aec6c7a6646c8893790be5c5f997..587503c41553fa7cd013cf5ad28862fa34f938a7 100644 (file)
@@ -137,21 +137,12 @@ Abort(void)
 
 
 static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = NULL;
-
-static void (*handler)(int) = NULL;
+static void (*gCallback)(void) = NULL;
 
 static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
 {
-    if (handler) {
-        int exceptionCode = 0;
-        if (pExceptionInfo) {
-            PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
-            if (pExceptionRecord) {
-                exceptionCode = pExceptionRecord->ExceptionCode;
-            }
-        }
-
-        handler(exceptionCode);
+    if (gCallback) {
+        gCallback();
     }
 
        if (prevExceptionFilter) {
@@ -162,18 +153,23 @@ static LONG WINAPI UnhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
 }
 
 void
-CatchInterrupts(void (*func)(int))
+SetExceptionCallback(void (*callback)(void))
 {
-    assert(!handler);
-    assert(!prevExceptionFilter);
+    assert(!gCallback);
 
-    handler = func;
+    if (!gCallback) {
+        gCallback = callback;
 
-    if (handler && !prevExceptionFilter) {
-        prevExceptionFilter =
-            SetUnhandledExceptionFilter(UnhandledExceptionFilter);
+        assert(!prevExceptionFilter);
+        prevExceptionFilter = SetUnhandledExceptionFilter(UnhandledExceptionFilter);
     }
 }
 
+void
+ResetExceptionCallback(void)
+{
+    gCallback = NULL;
+}
+
 
 } /* namespace OS */
index 90cc426cd7688d8a7014c3ca5e74b911734f5418..7e40e4676fb8c77ea6999d535c86c2c403d54cc5 100644 (file)
--- a/trace.py
+++ b/trace.py
@@ -60,10 +60,10 @@ class DumpDeclarator(stdapi.OnceVisitor):
         print '    static const Trace::StructSig sig = {'
         print '       %u, "%s", %u, members' % (int(struct.id), struct.name, len(struct.members))
         print '    };'
-        print '    __writer.beginStruct(&sig);'
+        print '    Trace::localWriter.beginStruct(&sig);'
         for type, name in struct.members:
             dump_instance(type, 'value.%s' % (name,))
-        print '    __writer.endStruct();'
+        print '    Trace::localWriter.endStruct();'
         print '}'
         print
 
@@ -90,10 +90,10 @@ class DumpDeclarator(stdapi.OnceVisitor):
             print '        sig = &sig%u;' % i
             print '        break;'
         print '    default:'
-        print '        __writer.writeSInt(value);'
+        print '        Trace::localWriter.writeSInt(value);'
         print '        return;'
         print '    }'
-        print '    __writer.writeEnum(sig);'
+        print '    Trace::localWriter.writeEnum(sig);'
         print '}'
         print
 
@@ -140,13 +140,13 @@ class DumpImplementer(stdapi.Visitor):
     '''Dump an instance.'''
 
     def visit_literal(self, literal, instance):
-        print '    __writer.write%s(%s);' % (literal.format, instance)
+        print '    Trace::localWriter.write%s(%s);' % (literal.format, instance)
 
     def visit_string(self, string, instance):
         if string.length is not None:
-            print '    __writer.writeString((const char *)%s, %s);' % (instance, string.length)
+            print '    Trace::localWriter.writeString((const char *)%s, %s);' % (instance, string.length)
         else:
-            print '    __writer.writeString((const char *)%s);' % instance
+            print '    Trace::localWriter.writeString((const char *)%s);' % instance
 
     def visit_const(self, const, instance):
         self.visit(const.type, instance)
@@ -159,35 +159,35 @@ class DumpImplementer(stdapi.Visitor):
         index = '__i' + array.type.id
         print '    if (%s) {' % instance
         print '        size_t %s = %s;' % (length, array.length)
-        print '        __writer.beginArray(%s);' % length
+        print '        Trace::localWriter.beginArray(%s);' % length
         print '        for (size_t %s = 0; %s < %s; ++%s) {' % (index, index, length, index)
-        print '            __writer.beginElement();'
+        print '            Trace::localWriter.beginElement();'
         self.visit(array.type, '(%s)[%s]' % (instance, index))
-        print '            __writer.endElement();'
+        print '            Trace::localWriter.endElement();'
         print '        }'
-        print '        __writer.endArray();'
+        print '        Trace::localWriter.endArray();'
         print '    } else {'
-        print '        __writer.writeNull();'
+        print '        Trace::localWriter.writeNull();'
         print '    }'
 
     def visit_blob(self, blob, instance):
-        print '    __writer.writeBlob(%s, %s);' % (instance, blob.size)
+        print '    Trace::localWriter.writeBlob(%s, %s);' % (instance, blob.size)
 
     def visit_enum(self, enum, instance):
         print '    __traceEnum%s(%s);' % (enum.id, instance)
 
     def visit_bitmask(self, bitmask, instance):
-        print '    __writer.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.id, instance)
+        print '    Trace::localWriter.writeBitmask(&__bitmask%s_sig, %s);' % (bitmask.id, instance)
 
     def visit_pointer(self, pointer, instance):
         print '    if (%s) {' % instance
-        print '        __writer.beginArray(1);'
-        print '        __writer.beginElement();'
+        print '        Trace::localWriter.beginArray(1);'
+        print '        Trace::localWriter.beginElement();'
         dump_instance(pointer.type, "*" + instance)
-        print '        __writer.endElement();'
-        print '        __writer.endArray();'
+        print '        Trace::localWriter.endElement();'
+        print '        Trace::localWriter.endArray();'
         print '    } else {'
-        print '        __writer.writeNull();'
+        print '        Trace::localWriter.writeNull();'
         print '    }'
 
     def visit_handle(self, handle, instance):
@@ -197,10 +197,10 @@ class DumpImplementer(stdapi.Visitor):
         self.visit(alias.type, instance)
 
     def visit_opaque(self, opaque, instance):
-        print '    __writer.writeOpaque((const void *)%s);' % instance
+        print '    Trace::localWriter.writeOpaque((const void *)%s);' % instance
 
     def visit_interface(self, interface, instance):
-        print '    __writer.writeOpaque((const void *)&%s);' % instance
+        print '    Trace::localWriter.writeOpaque((const void *)&%s);' % instance
 
 
 dump_instance = DumpImplementer().visit
@@ -309,8 +309,7 @@ class Tracer:
         self.footer(api)
 
     def header(self, api):
-        print 'Trace::LocalWriter __writer;'
-        print
+        pass
 
     def footer(self, api):
         pass
@@ -347,21 +346,21 @@ class Tracer:
         print
 
     def trace_function_impl_body(self, function):
-        print '    unsigned __call = __writer.beginEnter(&__%s_sig);' % (function.name,)
+        print '    unsigned __call = Trace::localWriter.beginEnter(&__%s_sig);' % (function.name,)
         for arg in function.args:
             if not arg.output:
                 self.unwrap_arg(function, arg)
                 self.dump_arg(function, arg)
-        print '    __writer.endEnter();'
+        print '    Trace::localWriter.endEnter();'
         self.dispatch_function(function)
-        print '    __writer.beginLeave(__call);'
+        print '    Trace::localWriter.beginLeave(__call);'
         for arg in function.args:
             if arg.output:
                 self.dump_arg(function, arg)
                 self.wrap_arg(function, arg)
         if function.type is not stdapi.Void:
             self.dump_ret(function, "__result")
-        print '    __writer.endLeave();'
+        print '    Trace::localWriter.endLeave();'
 
     def dispatch_function(self, function):
         if function.type is stdapi.Void:
@@ -372,9 +371,9 @@ class Tracer:
         print '    %s%s(%s);' % (result, dispatch, ', '.join([str(arg.name) for arg in function.args]))
 
     def dump_arg(self, function, arg):
-        print '    __writer.beginArg(%u);' % (arg.index,)
+        print '    Trace::localWriter.beginArg(%u);' % (arg.index,)
         self.dump_arg_instance(function, arg)
-        print '    __writer.endArg();'
+        print '    Trace::localWriter.endArg();'
 
     def dump_arg_instance(self, function, arg):
         dump_instance(arg.type, arg.name)
@@ -386,9 +385,9 @@ class Tracer:
         unwrap_instance(arg.type, arg.name)
 
     def dump_ret(self, function, instance):
-        print '    __writer.beginReturn();'
+        print '    Trace::localWriter.beginReturn();'
         dump_instance(function.type, instance)
-        print '    __writer.endReturn();'
+        print '    Trace::localWriter.endReturn();'
 
     def wrap_ret(self, function, instance):
         wrap_instance(function.type, instance)
@@ -412,10 +411,10 @@ class Tracer:
         print method.prototype(interface_wrap_name(interface) + '::' + method.name) + ' {'
         print '    static const char * __args[%u] = {%s};' % (len(method.args) + 1, ', '.join(['"this"'] + ['"%s"' % arg.name for arg in method.args]))
         print '    static const Trace::FunctionSig __sig = {%u, "%s", %u, __args};' % (int(method.id), interface.name + '::' + method.name, len(method.args) + 1)
-        print '    unsigned __call = __writer.beginEnter(&__sig);'
-        print '    __writer.beginArg(0);'
-        print '    __writer.writeOpaque((const void *)m_pInstance);'
-        print '    __writer.endArg();'
+        print '    unsigned __call = Trace::localWriter.beginEnter(&__sig);'
+        print '    Trace::localWriter.beginArg(0);'
+        print '    Trace::localWriter.writeOpaque((const void *)m_pInstance);'
+        print '    Trace::localWriter.endArg();'
         for arg in method.args:
             if not arg.output:
                 self.unwrap_arg(method, arg)
@@ -425,19 +424,19 @@ class Tracer:
         else:
             print '    %s __result;' % method.type
             result = '__result = '
-        print '    __writer.endEnter();'
+        print '    Trace::localWriter.endEnter();'
         print '    %sm_pInstance->%s(%s);' % (result, method.name, ', '.join([str(arg.name) for arg in method.args]))
-        print '    __writer.beginLeave(__call);'
+        print '    Trace::localWriter.beginLeave(__call);'
         for arg in method.args:
             if arg.output:
                 self.dump_arg(method, arg)
                 self.wrap_arg(method, arg)
         if method.type is not stdapi.Void:
-            print '    __writer.beginReturn();'
+            print '    Trace::localWriter.beginReturn();'
             dump_instance(method.type, "__result")
-            print '    __writer.endReturn();'
+            print '    Trace::localWriter.endReturn();'
             wrap_instance(method.type, '__result')
-        print '    __writer.endLeave();'
+        print '    Trace::localWriter.endLeave();'
         if method.name == 'QueryInterface':
             print '    if (ppvObj && *ppvObj) {'
             print '        if (*ppvObj == m_pInstance) {'
index 74cc3829e2b4ce5a18a3d69beb614e90b87ed6de..2a9705cd3350ffc49dacd604cde9ae137e47e82c 100644 (file)
@@ -9,56 +9,12 @@
 #include "os.hpp"
 
 #include <iostream>
-#include <set>
 
 using namespace Trace;
 
 #define SNAPPY_BYTE1 'a'
 #define SNAPPY_BYTE2 't'
 
-static void cleanupHandler(int sig);
-
-class FileCleanup
-{
-public:
-    FileCleanup()
-    {
-        OS::CatchInterrupts(cleanupHandler);
-    }
-
-    ~FileCleanup()
-    {
-        flush();
-        m_files.clear();
-    }
-
-    void addFile(Trace::File *file)
-    {
-        m_files.insert(file);
-    }
-    void removeFile(Trace::File *file)
-    {
-        m_files.erase(file);
-    }
-
-    void flush()
-    {
-        std::set<Trace::File*>::const_iterator itr;
-        for (itr = m_files.begin(); itr != m_files.end(); ++itr) {
-            (*itr)->flush(File::FlushDeep);
-        }
-    }
-
-private:
-    std::set<Trace::File*> m_files;
-};
-static FileCleanup s_cleaner;
-
-static void cleanupHandler(int sig)
-{
-    s_cleaner.flush();
-}
-
 File::File(const std::string &filename,
            File::Mode mode)
     : m_filename(filename),
@@ -99,9 +55,6 @@ bool File::open(const std::string &filename, File::Mode mode)
     m_isOpened = rawOpen(filename, mode);
     m_mode = mode;
 
-    if (m_isOpened) {
-        s_cleaner.addFile(this);
-    }
     return m_isOpened;
 }
 
@@ -126,7 +79,6 @@ void File::close()
     if (m_isOpened) {
         rawClose();
         m_isOpened = false;
-        s_cleaner.removeFile(this);
     }
 }
 
diff --git a/trace_local_writer.cpp b/trace_local_writer.cpp
new file mode 100644 (file)
index 0000000..ea6c111
--- /dev/null
@@ -0,0 +1,156 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2011 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "os.hpp"
+#include "trace_file.hpp"
+#include "trace_writer.hpp"
+#include "trace_format.hpp"
+
+
+namespace Trace {
+
+
+static void exceptionCallback(void)
+{
+    OS::DebugMessage("apitrace: flushing trace due to an exception\n");
+    localWriter.flush();
+}
+
+
+LocalWriter::LocalWriter() :
+    acquired(0)
+{}
+
+LocalWriter::~LocalWriter()
+{
+    OS::ResetExceptionCallback();
+}
+
+void
+LocalWriter::open(void) {
+
+    static unsigned dwCounter = 0;
+
+    const char *szExtension = "trace";
+    char szFileName[PATH_MAX];
+    const char *lpFileName;
+
+    lpFileName = getenv("TRACE_FILE");
+    if (lpFileName) {
+        strncpy(szFileName, lpFileName, PATH_MAX);
+    }
+    else {
+        char szProcessName[PATH_MAX];
+        char szCurrentDir[PATH_MAX];
+        OS::GetProcessName(szProcessName, PATH_MAX);
+        OS::GetCurrentDir(szCurrentDir, PATH_MAX);
+
+        for (;;) {
+            FILE *file;
+
+            if (dwCounter)
+                snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
+            else
+                snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
+
+            file = fopen(szFileName, "rb");
+            if (file == NULL)
+                break;
+
+            fclose(file);
+
+            ++dwCounter;
+        }
+    }
+
+    OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
+
+    Writer::open(szFileName);
+
+    OS::SetExceptionCallback(exceptionCallback);
+
+#if 0
+    // For debugging the exception handler
+    *((int *)0) = 0;
+#endif
+}
+
+unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
+    OS::AcquireMutex();
+    ++acquired;
+
+    if (!m_file->isOpened()) {
+        open();
+    }
+
+    return Writer::beginEnter(sig);
+}
+
+void LocalWriter::endEnter(void) {
+    Writer::endEnter();
+    --acquired;
+    OS::ReleaseMutex();
+}
+
+void LocalWriter::beginLeave(unsigned call) {
+    OS::AcquireMutex();
+    ++acquired;
+    Writer::beginLeave(call);
+}
+
+void LocalWriter::endLeave(void) {
+    Writer::endLeave();
+    --acquired;
+    OS::ReleaseMutex();
+}
+
+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.
+     */
+
+    if (!acquired) {
+        OS::AcquireMutex();
+        if (m_file->isOpened()) {
+            m_file->flush();
+        }
+        OS::ReleaseMutex();
+    }
+}
+
+
+LocalWriter localWriter;
+
+
+} /* namespace Trace */
+
index 057e3957be289a63b9598c3c4344ae75171cb71e..ce5df5c8b022d78d396c35160be3a2f88c8c93b0 100644 (file)
@@ -299,74 +299,5 @@ void Writer::writeOpaque(const void *addr) {
 }
 
 
-void
-LocalWriter::open(void) {
-
-    static unsigned dwCounter = 0;
-
-    const char *szExtension = "trace";
-    char szFileName[PATH_MAX];
-    const char *lpFileName;
-
-    lpFileName = getenv("TRACE_FILE");
-    if (lpFileName) {
-        strncpy(szFileName, lpFileName, PATH_MAX);
-    }
-    else {
-        char szProcessName[PATH_MAX];
-        char szCurrentDir[PATH_MAX];
-        OS::GetProcessName(szProcessName, PATH_MAX);
-        OS::GetCurrentDir(szCurrentDir, PATH_MAX);
-
-        for (;;) {
-            FILE *file;
-
-            if (dwCounter)
-                snprintf(szFileName, PATH_MAX, "%s%c%s.%u.%s", szCurrentDir, PATH_SEP, szProcessName, dwCounter, szExtension);
-            else
-                snprintf(szFileName, PATH_MAX, "%s%c%s.%s", szCurrentDir, PATH_SEP, szProcessName, szExtension);
-
-            file = fopen(szFileName, "rb");
-            if (file == NULL)
-                break;
-
-            fclose(file);
-
-            ++dwCounter;
-        }
-    }
-
-    OS::DebugMessage("apitrace: tracing to %s\n", szFileName);
-
-    Writer::open(szFileName);
-}
-
-unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
-    OS::AcquireMutex();
-
-    if (!m_file->isOpened()) {
-        open();
-    }
-
-    return Writer::beginEnter(sig);
-}
-
-void LocalWriter::endEnter(void) {
-    Writer::endEnter();
-    OS::ReleaseMutex();
-}
-
-void LocalWriter::beginLeave(unsigned call) {
-    OS::AcquireMutex();
-    Writer::beginLeave(call);
-}
-
-void LocalWriter::endLeave(void) {
-    Writer::endLeave();
-    m_file->flush();
-    OS::ReleaseMutex();
-}
-
-
 } /* namespace Trace */
 
index 4d46f739f8f231fcdee4e39de053b21949193448..dfb76b2508a4bac02f455b9d570cc733c5492f9a 100644 (file)
@@ -116,7 +116,15 @@ namespace Trace {
      */
     class LocalWriter : public Writer {
     protected:
+        int acquired;
+
     public:
+        /**
+         * Should never called directly -- use localWriter singleton below instead.
+         */
+        LocalWriter();
+        ~LocalWriter();
+
         void open(void);
 
         unsigned beginEnter(const FunctionSig *sig);
@@ -124,7 +132,14 @@ namespace Trace {
 
         void beginLeave(unsigned call);
         void endLeave(void);
+
+        void flush(void);
     };
+
+    /**
+     * Singleton.
+     */
+    extern LocalWriter localWriter;
 }
 
 #endif /* _TRACE_WRITER_HPP_ */