2 #include "bcwindowbase.inc"
8 BC_Signals* BC_Signals::global_signals = 0;
9 static int signal_done = 0;
10 static int table_id = 0;
12 static bc_locktrace_t* new_bc_locktrace(void *ptr,
16 bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t));
18 result->title = title;
19 result->location = location;
21 result->id = table_id++;
36 static bc_buffertrace_t* new_bc_buffertrace(int size, void *ptr, char *location)
38 bc_buffertrace_t *result = (bc_buffertrace_t*)malloc(sizeof(bc_buffertrace_t));
41 result->location = location;
50 // Need our own table to avoid recursion with the memory manager
58 static void* append_table(bc_table_t *table, void *ptr)
60 if(table->allocation <= table->size)
64 int new_allocation = table->allocation * 2;
65 void **new_values = (void**)calloc(new_allocation, sizeof(void*));
66 memcpy(new_values, table->values, sizeof(void*) * table->size);
68 table->values = new_values;
69 table->allocation = new_allocation;
73 table->allocation = 4096;
74 table->values = (void**)calloc(table->allocation, sizeof(void*));
78 table->values[table->size++] = ptr;
82 static void clear_table(bc_table_t *table, int delete_objects)
86 for(int i = 0; i < table->size; i++)
88 free(table->values[i]);
94 static void clear_table_entry(bc_table_t *table, int number, int delete_object)
96 if(delete_object) free(table->values[number]);
97 for(int i = number; i < table->size - 1; i++)
99 table->values[i] = table->values[i + 1];
105 // Table of functions currently running.
106 static bc_table_t execution_table = { 0, 0, 0 };
108 // Table of locked positions
109 static bc_table_t lock_table = { 0, 0, 0 };
112 static bc_table_t memory_table = { 0, 0, 0 };
114 static bc_table_t temp_files = { 0, 0, 0 };
116 // Can't use Mutex because it would be recursive
117 static pthread_mutex_t *lock = 0;
118 static pthread_mutex_t *handler_lock = 0;
119 // Don't trace memory until this is true to avoid initialization
120 static int trace_memory = 0;
123 static char* signal_titles[] =
143 static void signal_entry(int signum)
145 signal(signum, SIG_DFL);
147 pthread_mutex_lock(handler_lock);
150 pthread_mutex_unlock(handler_lock);
155 pthread_mutex_unlock(handler_lock);
158 printf("signal_entry: got %s my pid=%d execution table size=%d:\n",
159 signal_titles[signum],
161 execution_table.size);
163 BC_Signals::dump_traces();
164 BC_Signals::dump_locks();
165 BC_Signals::dump_buffers();
166 BC_Signals::delete_temps();
168 // Call user defined signal handler
169 BC_Signals::global_signals->signal_handler(signum);
174 static void signal_entry_recoverable(int signum)
176 printf("signal_entry_recoverable: got %s my pid=%d\n",
177 signal_titles[signum],
181 BC_Signals::BC_Signals()
185 void BC_Signals::dump_traces()
188 if(execution_table.size)
190 for(int i = 0; i < execution_table.size; i++)
191 printf(" %s\n", execution_table.values[i]);
196 void BC_Signals::dump_locks()
199 printf("signal_entry: lock table size=%d\n", lock_table.size);
200 for(int i = 0; i < lock_table.size; i++)
202 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
203 printf(" %p %s %s %s\n",
207 table->is_owner ? "*" : "");
212 void BC_Signals::dump_buffers()
214 pthread_mutex_lock(lock);
216 printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
217 for(int i = 0; i < memory_table.size; i++)
219 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
220 printf(" %d %p %s\n", entry->size, entry->ptr, entry->location);
222 pthread_mutex_unlock(lock);
225 void BC_Signals::delete_temps()
227 pthread_mutex_lock(lock);
228 printf("BC_Signals::delete_temps: deleting %d temp files\n", temp_files.size);
229 for(int i = 0; i < temp_files.size; i++)
231 printf(" %s\n", (char*)temp_files.values[i]);
232 remove((char*)temp_files.values[i]);
234 pthread_mutex_unlock(lock);
237 void BC_Signals::set_temp(char *string)
239 char *new_string = strdup(string);
240 append_table(&temp_files, new_string);
243 void BC_Signals::unset_temp(char *string)
245 for(int i = 0; i < temp_files.size; i++)
247 if(!strcmp((char*)temp_files.values[i], string))
249 clear_table_entry(&temp_files, i, 1);
256 void BC_Signals::initialize()
258 BC_Signals::global_signals = this;
259 lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
260 handler_lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
261 pthread_mutex_init(lock, 0);
262 pthread_mutex_init(handler_lock, 0);
268 void BC_Signals::initialize2()
270 signal(SIGHUP, signal_entry);
271 signal(SIGINT, signal_entry);
272 signal(SIGQUIT, signal_entry);
273 // SIGKILL cannot be stopped
274 // signal(SIGKILL, signal_entry);
275 signal(SIGSEGV, signal_entry);
276 signal(SIGTERM, signal_entry);
277 signal(SIGFPE, signal_entry_recoverable);
278 signal(SIGPIPE, signal_entry_recoverable);
282 void BC_Signals::signal_handler(int signum)
284 printf("BC_Signals::signal_handler\n");
288 char* BC_Signals::sig_to_str(int number)
290 return signal_titles[number];
293 #define TOTAL_TRACES 100
295 void BC_Signals::new_trace(char *text)
297 if(!global_signals) return;
298 pthread_mutex_lock(lock);
299 if(execution_table.size >= TOTAL_TRACES)
300 clear_table(&execution_table, 1);
301 append_table(&execution_table, strdup(text));
302 pthread_mutex_unlock(lock);
305 void BC_Signals::new_trace(const char *file, const char *function, int line)
307 char string[BCTEXTLEN];
308 snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line);
312 void BC_Signals::delete_traces()
314 if(!global_signals) return;
315 pthread_mutex_lock(lock);
316 clear_table(&execution_table, 0);
317 pthread_mutex_unlock(lock);
320 #define TOTAL_LOCKS 100
322 int BC_Signals::set_lock(void *ptr,
326 if(!global_signals) return 0;
327 bc_locktrace_t *table = 0;
330 pthread_mutex_lock(lock);
331 if(lock_table.size >= TOTAL_LOCKS)
332 clear_table(&lock_table, 0);
334 // Put new lock entry
335 table = new_bc_locktrace(ptr, title, location);
336 append_table(&lock_table, table);
337 id_return = table->id;
339 pthread_mutex_unlock(lock);
343 void BC_Signals::set_lock2(int table_id)
345 if(!global_signals) return;
347 bc_locktrace_t *table = 0;
348 pthread_mutex_lock(lock);
349 for(int i = lock_table.size - 1; i >= 0; i--)
351 table = (bc_locktrace_t*)lock_table.values[i];
352 // Got it. Hasn't been unlocked/deleted yet.
353 if(table->id == table_id)
356 pthread_mutex_unlock(lock);
360 pthread_mutex_unlock(lock);
363 void BC_Signals::unset_lock2(int table_id)
365 if(!global_signals) return;
367 bc_locktrace_t *table = 0;
368 pthread_mutex_lock(lock);
369 for(int i = lock_table.size - 1; i >= 0; i--)
371 table = (bc_locktrace_t*)lock_table.values[i];
372 if(table->id == table_id)
374 clear_table_entry(&lock_table, i, 1);
375 pthread_mutex_unlock(lock);
379 pthread_mutex_unlock(lock);
382 void BC_Signals::unset_lock(void *ptr)
384 if(!global_signals) return;
386 bc_locktrace_t *table = 0;
387 pthread_mutex_lock(lock);
389 // Take off currently held entry
390 for(int i = 0; i < lock_table.size; i++)
392 table = (bc_locktrace_t*)lock_table.values[i];
393 if(table->ptr == ptr)
397 clear_table_entry(&lock_table, i, 1);
398 pthread_mutex_unlock(lock);
404 pthread_mutex_unlock(lock);
408 void BC_Signals::unset_all_locks(void *ptr)
410 if(!global_signals) return;
411 pthread_mutex_lock(lock);
412 // Take off previous lock entry
413 for(int i = 0; i < lock_table.size; i++)
415 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
416 if(table->ptr == ptr)
418 clear_table_entry(&lock_table, i, 1);
421 pthread_mutex_unlock(lock);
425 void BC_Signals::enable_memory()
430 void BC_Signals::disable_memory()
436 void BC_Signals::set_buffer(int size, void *ptr, char* location)
438 if(!global_signals) return;
439 if(!trace_memory) return;
441 pthread_mutex_lock(lock);
442 append_table(&memory_table, new_bc_buffertrace(size, ptr, location));
443 pthread_mutex_unlock(lock);
446 int BC_Signals::unset_buffer(void *ptr)
448 if(!global_signals) return 0;
449 if(!trace_memory) return 0;
450 pthread_mutex_lock(lock);
451 for(int i = 0; i < memory_table.size; i++)
453 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
455 clear_table_entry(&memory_table, i, 1);
456 pthread_mutex_unlock(lock);
460 pthread_mutex_unlock(lock);
461 fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
479 // Vice president of memory management
480 void* operator new(size_t size)
482 //printf("new 1 %d\n", size);
483 void *result = malloc(size);
484 BUFFER(size, result, "new");
485 //printf("new 2 %d\n", size);
489 void* operator new[](size_t size)
491 //printf("new [] 1 %d\n", size);
492 void *result = malloc(size);
493 BUFFER(size, result, "new []");
494 //printf("new [] 2 %d\n", size);
498 void operator delete(void *ptr)
500 //printf("delete 1 %p\n", ptr);
502 //printf("delete 2 %p\n", ptr);
506 void operator delete[](void *ptr)
508 //printf("delete [] 1 %p\n", ptr);
511 //printf("delete [] 2 %p\n", ptr);