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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user