wvcrashbase.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 2005 Net Integration Technologies, Inc.
00004  *
00005  * Routines to save messages that can be logged when a program crashes.
00006  */
00007 #include "wvcrash.h"
00008 
00009 #include <errno.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 
00014 // FIXME: this file mostly only works in Linux
00015 #ifdef __linux
00016 
00017 #ifdef __USE_GNU
00018 static const char *argv0 = program_invocation_short_name;
00019 #else
00020 static const char *argv0 = "UNKNOWN";
00021 #endif // __USE_GNU
00022 
00023 // Reserve enough buffer for a screenful of programme.
00024 static const int buffer_size = 2048;
00025 static char will_msg[buffer_size];
00026 static char assert_msg[buffer_size];
00027 
00028 static const int ring_buffer_order = wvcrash_ring_buffer_order;
00029 static const int ring_buffer_size = wvcrash_ring_buffer_size;
00030 static const int ring_buffer_mask = ring_buffer_size - 1;
00031 static char ring_buffer[ring_buffer_size+1];
00032 static int ring_buffer_start = 0, ring_buffer_used = 0;
00033 
00034 extern "C"
00035 {
00036     // Support assert().
00037     void __assert_fail(const char *__assertion, const char *__file,
00038                        unsigned int __line, const char *__function)
00039     {
00040         // Set the assert message that WvCrash will dump.
00041         snprintf(assert_msg, buffer_size,
00042                  "%s: %s:%u: %s: Assertion `%s' failed.\n",
00043                  argv0, __file, __line, __function, __assertion);
00044         assert_msg[buffer_size - 1] = '\0';
00045 
00046         // Emulate the GNU C library's __assert_fail().
00047         fprintf(stderr, "%s: %s:%u: %s: Assertion `%s' failed.\n",
00048                 argv0, __file, __line, __function, __assertion);
00049         abort();
00050     }
00051 
00052 
00053     // Wrapper for standards compliance.
00054     void __assert(const char *__assertion, const char *__file,
00055                   unsigned int __line, const char *__function)
00056     {
00057         __assert_fail(__assertion, __file, __line, __function);
00058     }
00059 
00060 
00061     // Support the GNU assert_perror() extension.
00062     void __assert_perror_fail(int __errnum, const char *__file,
00063                               unsigned int __line, const char *__function)
00064     {
00065         // Set the assert message that WvCrash will dump.
00066         snprintf(assert_msg, buffer_size,
00067                  "%s: %s:%u: %s: Unexpected error: %s.\n",
00068                  argv0, __file, __line, __function, strerror(__errnum));
00069         assert_msg[buffer_size - 1] = '\0';
00070 
00071         // Emulate the GNU C library's __assert_perror_fail().
00072         fprintf(stderr, "%s: %s:%u: %s: Unexpected error: %s.\n",
00073                 argv0, __file, __line, __function, strerror(__errnum));
00074         abort();
00075     }
00076 } // extern "C"
00077 
00078 
00079 // This function is meant to support people who wish to leave a last will
00080 // and testament in the WvCrash.
00081 void wvcrash_leave_will(const char *will)
00082 {
00083     if (will)
00084     {
00085         strncpy(will_msg, will, buffer_size);
00086         will_msg[buffer_size - 1] = '\0';
00087     }
00088     else
00089         will_msg[0] = '\0';
00090 }
00091 
00092 
00093 const char *wvcrash_read_will()
00094 {
00095     return will_msg;
00096 }
00097 
00098 
00099 const char *wvcrash_read_assert()
00100 {
00101     return assert_msg;
00102 }
00103 
00104 
00105 void wvcrash_ring_buffer_put(const char *str)
00106 {
00107     wvcrash_ring_buffer_put(str, strlen(str));
00108 }
00109 
00110 
00111 void wvcrash_ring_buffer_put(const char *str, size_t len)
00112 {
00113     while (len > 0)
00114     {
00115         int pos = (ring_buffer_start + ring_buffer_used) & ring_buffer_mask;
00116         ring_buffer[pos] = *str++;
00117         --len;
00118         if (ring_buffer_used == ring_buffer_size)
00119             ring_buffer_start = (ring_buffer_start + 1) & ring_buffer_mask;
00120         else
00121             ++ring_buffer_used;
00122     }
00123 }
00124 
00125 
00126 const char *wvcrash_ring_buffer_get()
00127 {
00128     if (ring_buffer_used == 0)
00129         return NULL;
00130     const char *result;
00131     if (ring_buffer_start + ring_buffer_used >= ring_buffer_size)
00132     {
00133         ring_buffer[ring_buffer_size] = '\0';
00134         result = &ring_buffer[ring_buffer_start];
00135         ring_buffer_used -= ring_buffer_size - ring_buffer_start;
00136         ring_buffer_start = 0;
00137     }
00138     else
00139     {
00140         ring_buffer[ring_buffer_start + ring_buffer_used] = '\0';
00141         result = &ring_buffer[ring_buffer_start];
00142         ring_buffer_start += ring_buffer_used;
00143         ring_buffer_used = 0;
00144     }
00145     return result;
00146 }
00147 
00148 
00149 void __wvcrash_init_buffers(const char *program_name)
00150 {
00151     if (program_name)
00152         argv0 = program_name;
00153     will_msg[0] = '\0';
00154     assert_msg[0] = '\0';
00155 }
00156 
00157 
00158 #else // __linux
00159 
00160 void wvcrash_leave_will(const char *will) {}
00161 const char *wvcrash_read_will() { return NULL; }
00162 
00163 #endif // __linux

Generated on Fri Oct 5 18:20:27 2007 for WvStreams by  doxygen 1.5.3