WvStreams
wvcrashbase.cc
1 /*
2  * Worldvisions Weaver Software:
3  * Copyright (C) 2005 Net Integration Technologies, Inc.
4  *
5  * Routines to save messages that can be logged when a program crashes.
6  */
7 #include "wvcrash.h"
8 
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 IWvStream *WvCrashInfo::in_stream = NULL;
15 const char *WvCrashInfo::in_stream_id = NULL;
16 enum WvCrashInfo::InStreamState WvCrashInfo::in_stream_state = UNUSED;
17 static const int ring_buffer_order = wvcrash_ring_buffer_order;
18 static const int ring_buffer_size = wvcrash_ring_buffer_size;
19 static const int ring_buffer_mask = ring_buffer_size - 1;
20 static char ring_buffer[ring_buffer_size+1];
21 static int ring_buffer_start = 0, ring_buffer_used = 0;
22 
23 void wvcrash_ring_buffer_put(const char *str)
24 {
25  wvcrash_ring_buffer_put(str, strlen(str));
26 }
27 
28 
29 void wvcrash_ring_buffer_put(const char *str, size_t len)
30 {
31  while (len > 0)
32  {
33  int pos = (ring_buffer_start + ring_buffer_used) & ring_buffer_mask;
34  ring_buffer[pos] = *str++;
35  --len;
36  if (ring_buffer_used == ring_buffer_size)
37  ring_buffer_start = (ring_buffer_start + 1) & ring_buffer_mask;
38  else
39  ++ring_buffer_used;
40  }
41 }
42 
43 
44 const char *wvcrash_ring_buffer_get()
45 {
46  if (ring_buffer_used == 0)
47  return NULL;
48  const char *result;
49  if (ring_buffer_start + ring_buffer_used >= ring_buffer_size)
50  {
51  ring_buffer[ring_buffer_size] = '\0';
52  result = &ring_buffer[ring_buffer_start];
53  ring_buffer_used -= ring_buffer_size - ring_buffer_start;
54  ring_buffer_start = 0;
55  }
56  else
57  {
58  ring_buffer[ring_buffer_start + ring_buffer_used] = '\0';
59  result = &ring_buffer[ring_buffer_start];
60  ring_buffer_start += ring_buffer_used;
61  ring_buffer_used = 0;
62  }
63  return result;
64 }
65 
66 
67 
68 // FIXME: leaving of a will and catching asserts mostly only works in Linux
69 #ifdef __linux
70 
71 #ifdef __USE_GNU
72 static const char *argv0 = program_invocation_short_name;
73 #else
74 static const char *argv0 = "UNKNOWN";
75 #endif // __USE_GNU
76 
77 // Reserve enough buffer for a screenful of programme.
78 static const int buffer_size = 2048;
79 static char will_msg[buffer_size];
80 static char assert_msg[buffer_size];
81 
82 
83 extern "C"
84 {
85  // Support assert().
86  void __assert_fail(const char *__assertion, const char *__file,
87  unsigned int __line, const char *__function)
88  {
89  // Set the assert message that WvCrash will dump.
90  snprintf(assert_msg, buffer_size,
91  "%s: %s:%u: %s: Assertion `%s' failed.\n",
92  argv0, __file, __line, __function, __assertion);
93  assert_msg[buffer_size - 1] = '\0';
94 
95  // Emulate the GNU C library's __assert_fail().
96  fprintf(stderr, "%s: %s:%u: %s: Assertion `%s' failed.\n",
97  argv0, __file, __line, __function, __assertion);
98  abort();
99  }
100 
101 
102  // Wrapper for standards compliance.
103  void __assert(const char *__assertion, const char *__file,
104  unsigned int __line, const char *__function)
105  {
106  __assert_fail(__assertion, __file, __line, __function);
107  }
108 
109 
110  // Support the GNU assert_perror() extension.
111  void __assert_perror_fail(int __errnum, const char *__file,
112  unsigned int __line, const char *__function)
113  {
114  // Set the assert message that WvCrash will dump.
115  snprintf(assert_msg, buffer_size,
116  "%s: %s:%u: %s: Unexpected error: %s.\n",
117  argv0, __file, __line, __function, strerror(__errnum));
118  assert_msg[buffer_size - 1] = '\0';
119 
120  // Emulate the GNU C library's __assert_perror_fail().
121  fprintf(stderr, "%s: %s:%u: %s: Unexpected error: %s.\n",
122  argv0, __file, __line, __function, strerror(__errnum));
123  abort();
124  }
125 } // extern "C"
126 
127 
128 // This function is meant to support people who wish to leave a last will
129 // and testament in the WvCrash.
130 void wvcrash_leave_will(const char *will)
131 {
132  if (will)
133  {
134  strncpy(will_msg, will, buffer_size);
135  will_msg[buffer_size - 1] = '\0';
136  }
137  else
138  will_msg[0] = '\0';
139 }
140 
141 
142 const char *wvcrash_read_will()
143 {
144  return will_msg;
145 }
146 
147 
148 const char *wvcrash_read_assert()
149 {
150  return assert_msg;
151 }
152 
153 
154 void __wvcrash_init_buffers(const char *program_name)
155 {
156  if (program_name)
157  argv0 = program_name;
158  will_msg[0] = '\0';
159  assert_msg[0] = '\0';
160 }
161 
162 
163 #else // this is NOT __linux
164 
165 void wvcrash_leave_will(const char *will) {}
166 const char *wvcrash_read_will() { return NULL; }
167 
168 #endif // __linux
IWvStream
Definition: iwvstream.h:24