From: José Fonseca Date: Wed, 24 Aug 2011 18:58:47 +0000 (+0100) Subject: Merge branch 'master' into compression X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=1035b94bc86d70dc0f6af1adcf7f20fd5d2bdca3;hp=f32476d63b395c2d844247bd4d7fae4173df4065;p=apitrace Merge branch 'master' into compression Conflicts: os.hpp os_posix.cpp os_win32.cpp trace_writer.cpp --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 67d327a..39ffde5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 f5fb76e..f579a9b 100644 --- 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 a63b805..640d218 100644 --- 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) diff --git a/gltrace.py b/gltrace.py index af57142..9224bbe 100644 --- a/gltrace.py +++ b/gltrace.py @@ -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 e93b113..8e487b5 100644 --- 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 */ diff --git a/os_posix.cpp b/os_posix.cpp index c072d5d..991ad0e 100644 --- a/os_posix.cpp +++ b/os_posix.cpp @@ -24,6 +24,7 @@ **************************************************************************/ +#include #include #include #include @@ -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 */ diff --git a/os_win32.cpp b/os_win32.cpp index a35e2a3..587503c 100644 --- a/os_win32.cpp +++ b/os_win32.cpp @@ -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 */ diff --git a/trace.py b/trace.py index 90cc426..7e40e46 100644 --- 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) {' diff --git a/trace_file.cpp b/trace_file.cpp index 74cc382..2a9705c 100644 --- a/trace_file.cpp +++ b/trace_file.cpp @@ -9,56 +9,12 @@ #include "os.hpp" #include -#include 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::const_iterator itr; - for (itr = m_files.begin(); itr != m_files.end(); ++itr) { - (*itr)->flush(File::FlushDeep); - } - } - -private: - std::set 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 index 0000000..ea6c111 --- /dev/null +++ b/trace_local_writer.cpp @@ -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 +#include +#include +#include +#include + +#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 */ + diff --git a/trace_writer.cpp b/trace_writer.cpp index 057e395..ce5df5c 100644 --- a/trace_writer.cpp +++ b/trace_writer.cpp @@ -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 */ diff --git a/trace_writer.hpp b/trace_writer.hpp index 4d46f73..dfb76b2 100644 --- a/trace_writer.hpp +++ b/trace_writer.hpp @@ -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_ */