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
This commit is contained in:
avolkov
2006-04-28 01:28:27 +00:00
parent 3e94beb605
commit 1afd2a8a1f
2 changed files with 75 additions and 29 deletions
+72 -25
View File
@@ -17,6 +17,8 @@
#include "uqmlog.h" #include "uqmlog.h"
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <signal.h>
#include <errno.h>
#include "libs/threadlib.h" #include "libs/threadlib.h"
#ifndef MAX_LOG_ENTRY_SIZE #ifndef MAX_LOG_ENTRY_SIZE
@@ -34,20 +36,25 @@ static log_Entry queue[MAX_LOG_ENTRIES];
static log_Entry msgNoThread; static log_Entry msgNoThread;
static char msgBuf[16384]; static char msgBuf[16384];
static int maxLevel = log_Debug; static int maxLevel = log_Always;
static int maxStreamLevel = log_Debug; static int maxStreamLevel = log_Debug;
static int maxDisp = 10; static int maxDisp = 10;
static int qtotal = 0; static int qtotal = 0;
static int qhead = 0; static int qhead = 0;
static int qtail = 0; static int qtail = 0;
static volatile bool noThreadReady = 0; static volatile bool noThreadReady = false;
static bool forceBox = 0; static bool showBox = true;
static bool errorBox = true;
static FILE *streamOut; static FILE *streamOut;
static volatile int qlock = 0; static volatile int qlock = 0;
static Mutex qmutex; static Mutex qmutex;
static void (* prevAbortFunc)(int) = SIG_ERR;
static void exitCallback (void);
static void abortHandler (int);
static void displayLog (bool isError); static void displayLog (bool isError);
static void displayBox (const char *title, bool isError, const char *msg); 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'; msgBuf[sizeof (msgBuf) - 1] = '\0';
msgNoThread[sizeof (msgNoThread) - 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 void
@@ -143,10 +159,7 @@ log_initThreads (void)
int int
log_exit (int code) log_exit (int code)
{ {
if (code != EXIT_SUCCESS) showBox = false;
displayLog (true);
else if (forceBox)
displayLog (false);
if (qlock) if (qlock)
{ {
@@ -154,14 +167,10 @@ log_exit (int code)
DestroyMutex (qmutex); DestroyMutex (qmutex);
} }
return code; if (prevAbortFunc != SIG_ERR)
} signal (SIGABRT, prevAbortFunc);
void return code;
logged_abort (void)
{
log_exit (3);
abort ();
} }
void void
@@ -240,9 +249,10 @@ log_add_nothread (log_Level level, const char *fmt, ...)
} }
void 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 // sets the maximum log lines captured for the final
@@ -262,14 +272,36 @@ log_captureLines (int num)
unlockQueue (); 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 static void
displayLog (bool isError) displayLog (bool isError)
{ {
char *p = msgBuf; char *p = msgBuf;
int left = sizeof (msgBuf) - 1; int left = sizeof (msgBuf) - 1;
int len; int len;
int ptr;
queueNonThreaded ();
if (isError) if (isError)
{ {
@@ -280,20 +312,35 @@ displayLog (bool isError)
left -= len; left -= len;
} }
// glue the log entries together // Glue the log entries together
lockQueue (); // Locking is not a good idea at this point and we do not
while (qtail != qhead && left > 0) // 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) if (len > left)
len = left; len = left;
memcpy (p, queue[qtail], len); memcpy (p, queue[ptr], len);
p[len - 1] = '\n'; p[len - 1] = '\n';
p += len; p += len;
left -= 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); displayBox ("The Ur-Quan Masters", isError, msgBuf);
} }
+3 -4
View File
@@ -25,23 +25,22 @@
extern void log_init (int max_lines); extern void log_init (int max_lines);
extern void log_initThreads (void); extern void log_initThreads (void);
extern int log_exit (int code); 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); extern FILE * log_setOutput (FILE *out);
// sets the new output stream and returns the previous one // sets the new output stream and returns the previous one
extern void log_setLevel (int level); 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); extern void log_captureLines (int num);
#define LOG_CAPTURE_ALL 1000000 // unreasonably big number #define LOG_CAPTURE_ALL 1000000 // unreasonably big number
typedef enum typedef enum
{ {
log_Never = -1, log_Nothing = -1,
log_Always = 0, log_Always = 0,
log_Warning, log_Warning,
log_Info, log_Info,
log_Debug, log_Debug,
log_Never,
} log_Level; } log_Level;