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