From 1afd2a8a1fc2275574fd2398729d1db2aa781155 Mon Sep 17 00:00:00 2001 From: avolkov Date: Fri, 28 Apr 2006 01:28:27 +0000 Subject: [PATCH] Now using atexit() callback and SIGABRT handled git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2332 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/log/uqmlog.c | 97 +++++++++++++++++++++++-------- sc2/src/sc2code/libs/log/uqmlog.h | 7 +-- 2 files changed, 75 insertions(+), 29 deletions(-) diff --git a/sc2/src/sc2code/libs/log/uqmlog.c b/sc2/src/sc2code/libs/log/uqmlog.c index 56329c6ed..dd0a82199 100755 --- a/sc2/src/sc2code/libs/log/uqmlog.c +++ b/sc2/src/sc2code/libs/log/uqmlog.c @@ -17,6 +17,8 @@ #include "uqmlog.h" #include #include +#include +#include #include "libs/threadlib.h" #ifndef MAX_LOG_ENTRY_SIZE @@ -34,20 +36,25 @@ static log_Entry queue[MAX_LOG_ENTRIES]; static log_Entry msgNoThread; static char msgBuf[16384]; -static int maxLevel = log_Debug; +static int maxLevel = log_Always; static int maxStreamLevel = log_Debug; static int maxDisp = 10; static int qtotal = 0; static int qhead = 0; static int qtail = 0; -static volatile bool noThreadReady = 0; -static bool forceBox = 0; +static volatile bool noThreadReady = false; +static bool showBox = true; +static bool errorBox = true; static FILE *streamOut; static volatile int qlock = 0; static Mutex qmutex; +static void (* prevAbortFunc)(int) = SIG_ERR; + +static void exitCallback (void); +static void abortHandler (int); static void displayLog (bool isError); static void displayBox (const char *title, bool isError, const char *msg); @@ -131,6 +138,15 @@ log_init (int max_lines) msgBuf[sizeof (msgBuf) - 1] = '\0'; msgNoThread[sizeof (msgNoThread) - 1] = '\0'; + + // install exit and abort handlers + atexit (exitCallback); + prevAbortFunc = signal (SIGABRT, abortHandler); + if (prevAbortFunc == SIG_ERR) + { + fprintf (stderr, "Warning: cannot install SIGABRT handler, code %d\n", + errno); + } } void @@ -143,10 +159,7 @@ log_initThreads (void) int log_exit (int code) { - if (code != EXIT_SUCCESS) - displayLog (true); - else if (forceBox) - displayLog (false); + showBox = false; if (qlock) { @@ -154,14 +167,10 @@ log_exit (int code) DestroyMutex (qmutex); } - return code; -} + if (prevAbortFunc != SIG_ERR) + signal (SIGABRT, prevAbortFunc); -void -logged_abort (void) -{ - log_exit (3); - abort (); + return code; } void @@ -240,9 +249,10 @@ log_add_nothread (log_Level level, const char *fmt, ...) } void -log_forceBox (bool force) +log_showBox (bool show, bool err) { - forceBox = force; + showBox = show; + errorBox = err; } // sets the maximum log lines captured for the final @@ -262,14 +272,36 @@ log_captureLines (int num) unlockQueue (); } +static void +exitCallback (void) +{ + if (showBox) + displayLog (errorBox); + + log_exit (0); +} + +static void +abortHandler (int sig) +{ + if (showBox) + displayLog (true); + + if (prevAbortFunc == SIG_ERR || prevAbortFunc == SIG_IGN) + ; // do nothing + else if (prevAbortFunc == SIG_DFL) + raise (SIGABRT); // forward to default + else + prevAbortFunc (sig); // forward directly +} + static void displayLog (bool isError) { char *p = msgBuf; int left = sizeof (msgBuf) - 1; int len; - - queueNonThreaded (); + int ptr; if (isError) { @@ -280,20 +312,35 @@ displayLog (bool isError) left -= len; } - // glue the log entries together - lockQueue (); - while (qtail != qhead && left > 0) + // Glue the log entries together + // Locking is not a good idea at this point and we do not + // really need it -- the worst that can happen is we get + // an extra or an incomplete message + for (ptr = qtail; ptr != qhead && left > 0; + ptr = (ptr + 1) % MAX_LOG_ENTRIES) { - len = strlen (queue[qtail]) + 1; + len = strlen (queue[ptr]) + 1; if (len > left) len = left; - memcpy (p, queue[qtail], len); + memcpy (p, queue[ptr], len); p[len - 1] = '\n'; p += len; left -= len; - qtail = (qtail + 1) % MAX_LOG_ENTRIES; } - unlockQueue (); + + // Glue the non-threaded message if present + if (noThreadReady) + { + noThreadReady = false; + len = strlen (msgNoThread); + if (len > left) + len = left; + memcpy (p, msgNoThread, len); + p += len; + left -= len; + } + + *p = '\0'; displayBox ("The Ur-Quan Masters", isError, msgBuf); } diff --git a/sc2/src/sc2code/libs/log/uqmlog.h b/sc2/src/sc2code/libs/log/uqmlog.h index c32b12316..717c322f6 100755 --- a/sc2/src/sc2code/libs/log/uqmlog.h +++ b/sc2/src/sc2code/libs/log/uqmlog.h @@ -25,23 +25,22 @@ extern void log_init (int max_lines); extern void log_initThreads (void); extern int log_exit (int code); -static inline void logged_exit (int code) { exit (log_exit (code)); } -extern void logged_abort (void); extern FILE * log_setOutput (FILE *out); // sets the new output stream and returns the previous one extern void log_setLevel (int level); -extern void log_forceBox (bool force); +extern void log_showBox (bool show, bool err); extern void log_captureLines (int num); #define LOG_CAPTURE_ALL 1000000 // unreasonably big number typedef enum { - log_Never = -1, + log_Nothing = -1, log_Always = 0, log_Warning, log_Info, log_Debug, + log_Never, } log_Level;