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
56 // This points to the next value to replace if the table wraps around
60 static void* append_table(bc_table_t *table, void *ptr)
62 if(table->allocation <= table->size)
66 int new_allocation = table->allocation * 2;
67 void **new_values = (void**)calloc(new_allocation, sizeof(void*));
68 memcpy(new_values, table->values, sizeof(void*) * table->size);
70 table->values = new_values;
71 table->allocation = new_allocation;
75 table->allocation = 4096;
76 table->values = (void**)calloc(table->allocation, sizeof(void*));
80 table->values[table->size++] = ptr;
84 // Replace item in table pointed to by current_value and advance
86 static void* overwrite_table(bc_table_t *table, void *ptr)
88 free(table->values[table->current_value]);
89 table->values[table->current_value++] = ptr;
90 if(table->current_value >= table->size) table->current_value = 0;
93 static void clear_table(bc_table_t *table, int delete_objects)
97 for(int i = 0; i < table->size; i++)
99 free(table->values[i]);
105 static void clear_table_entry(bc_table_t *table, int number, int delete_object)
107 if(delete_object) free(table->values[number]);
108 for(int i = number; i < table->size - 1; i++)
110 table->values[i] = table->values[i + 1];
116 // Table of functions currently running.
117 static bc_table_t execution_table = { 0, 0, 0, 0 };
119 // Table of locked positions
120 static bc_table_t lock_table = { 0, 0, 0, 0 };
123 static bc_table_t memory_table = { 0, 0, 0, 0 };
125 static bc_table_t temp_files = { 0, 0, 0, 0 };
127 // Can't use Mutex because it would be recursive
128 static pthread_mutex_t *lock = 0;
129 static pthread_mutex_t *handler_lock = 0;
130 // Don't trace memory until this is true to avoid initialization
131 static int trace_memory = 0;
134 static char* signal_titles[] =
154 static void signal_entry(int signum)
156 signal(signum, SIG_DFL);
158 pthread_mutex_lock(handler_lock);
161 pthread_mutex_unlock(handler_lock);
166 pthread_mutex_unlock(handler_lock);
169 printf("signal_entry: got %s my pid=%d execution table size=%d:\n",
170 signal_titles[signum],
172 execution_table.size);
174 BC_Signals::dump_traces();
175 BC_Signals::dump_locks();
176 BC_Signals::dump_buffers();
177 BC_Signals::delete_temps();
179 // Call user defined signal handler
180 BC_Signals::global_signals->signal_handler(signum);
185 static void signal_entry_recoverable(int signum)
187 printf("signal_entry_recoverable: got %s my pid=%d\n",
188 signal_titles[signum],
192 BC_Signals::BC_Signals()
196 void BC_Signals::dump_traces()
199 if(execution_table.size)
201 for(int i = execution_table.current_value; i < execution_table.size; i++)
202 printf(" %s\n", execution_table.values[i]);
203 for(int i = 0; i < execution_table.current_value; i++)
204 printf(" %s\n", execution_table.values[i]);
209 void BC_Signals::dump_locks()
212 printf("signal_entry: lock table size=%d\n", lock_table.size);
213 for(int i = 0; i < lock_table.size; i++)
215 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
216 printf(" %p %s %s %s\n",
220 table->is_owner ? "*" : "");
225 void BC_Signals::dump_buffers()
227 pthread_mutex_lock(lock);
229 printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
230 for(int i = 0; i < memory_table.size; i++)
232 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
233 printf(" %d %p %s\n", entry->size, entry->ptr, entry->location);
235 pthread_mutex_unlock(lock);
238 void BC_Signals::delete_temps()
240 pthread_mutex_lock(lock);
241 printf("BC_Signals::delete_temps: deleting %d temp files\n", temp_files.size);
242 for(int i = 0; i < temp_files.size; i++)
244 printf(" %s\n", (char*)temp_files.values[i]);
245 remove((char*)temp_files.values[i]);
247 pthread_mutex_unlock(lock);
250 void BC_Signals::set_temp(char *string)
252 char *new_string = strdup(string);
253 append_table(&temp_files, new_string);
256 void BC_Signals::unset_temp(char *string)
258 for(int i = 0; i < temp_files.size; i++)
260 if(!strcmp((char*)temp_files.values[i], string))
262 clear_table_entry(&temp_files, i, 1);
269 void BC_Signals::initialize()
271 BC_Signals::global_signals = this;
272 lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
273 handler_lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
274 pthread_mutex_init(lock, 0);
275 pthread_mutex_init(handler_lock, 0);
281 void BC_Signals::initialize2()
283 signal(SIGHUP, signal_entry);
284 signal(SIGINT, signal_entry);
285 signal(SIGQUIT, signal_entry);
286 // SIGKILL cannot be stopped
287 // signal(SIGKILL, signal_entry);
288 signal(SIGSEGV, signal_entry);
289 signal(SIGTERM, signal_entry);
290 signal(SIGFPE, signal_entry);
291 signal(SIGPIPE, signal_entry_recoverable);
295 void BC_Signals::signal_handler(int signum)
297 printf("BC_Signals::signal_handler\n");
301 char* BC_Signals::sig_to_str(int number)
303 return signal_titles[number];
306 #define TOTAL_TRACES 16
308 void BC_Signals::new_trace(char *text)
310 if(!global_signals) return;
311 pthread_mutex_lock(lock);
314 if(execution_table.size >= TOTAL_TRACES)
316 overwrite_table(&execution_table, strdup(text));
317 // clear_table(&execution_table, 1);
321 append_table(&execution_table, strdup(text));
323 pthread_mutex_unlock(lock);
326 void BC_Signals::new_trace(const char *file, const char *function, int line)
328 char string[BCTEXTLEN];
329 snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line);
333 void BC_Signals::delete_traces()
335 if(!global_signals) return;
336 pthread_mutex_lock(lock);
337 clear_table(&execution_table, 0);
338 pthread_mutex_unlock(lock);
341 #define TOTAL_LOCKS 100
343 int BC_Signals::set_lock(void *ptr,
347 if(!global_signals) return 0;
348 bc_locktrace_t *table = 0;
351 pthread_mutex_lock(lock);
352 if(lock_table.size >= TOTAL_LOCKS)
353 clear_table(&lock_table, 0);
355 // Put new lock entry
356 table = new_bc_locktrace(ptr, title, location);
357 append_table(&lock_table, table);
358 id_return = table->id;
360 pthread_mutex_unlock(lock);
364 void BC_Signals::set_lock2(int table_id)
366 if(!global_signals) return;
368 bc_locktrace_t *table = 0;
369 pthread_mutex_lock(lock);
370 for(int i = lock_table.size - 1; i >= 0; i--)
372 table = (bc_locktrace_t*)lock_table.values[i];
373 // Got it. Hasn't been unlocked/deleted yet.
374 if(table->id == table_id)
377 pthread_mutex_unlock(lock);
381 pthread_mutex_unlock(lock);
384 void BC_Signals::unset_lock2(int table_id)
386 if(!global_signals) return;
388 bc_locktrace_t *table = 0;
389 pthread_mutex_lock(lock);
390 for(int i = lock_table.size - 1; i >= 0; i--)
392 table = (bc_locktrace_t*)lock_table.values[i];
393 if(table->id == table_id)
395 clear_table_entry(&lock_table, i, 1);
396 pthread_mutex_unlock(lock);
400 pthread_mutex_unlock(lock);
403 void BC_Signals::unset_lock(void *ptr)
405 if(!global_signals) return;
407 bc_locktrace_t *table = 0;
408 pthread_mutex_lock(lock);
410 // Take off currently held entry
411 for(int i = 0; i < lock_table.size; i++)
413 table = (bc_locktrace_t*)lock_table.values[i];
414 if(table->ptr == ptr)
418 clear_table_entry(&lock_table, i, 1);
419 pthread_mutex_unlock(lock);
425 pthread_mutex_unlock(lock);
429 void BC_Signals::unset_all_locks(void *ptr)
431 if(!global_signals) return;
432 pthread_mutex_lock(lock);
433 // Take off previous lock entry
434 for(int i = 0; i < lock_table.size; i++)
436 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
437 if(table->ptr == ptr)
439 clear_table_entry(&lock_table, i, 1);
442 pthread_mutex_unlock(lock);
446 void BC_Signals::enable_memory()
451 void BC_Signals::disable_memory()
457 void BC_Signals::set_buffer(int size, void *ptr, char* location)
459 if(!global_signals) return;
460 if(!trace_memory) return;
462 //printf("BC_Signals::set_buffer %p %s\n", ptr, location);
463 pthread_mutex_lock(lock);
464 append_table(&memory_table, new_bc_buffertrace(size, ptr, location));
465 pthread_mutex_unlock(lock);
468 int BC_Signals::unset_buffer(void *ptr)
470 if(!global_signals) return 0;
471 if(!trace_memory) return 0;
473 pthread_mutex_lock(lock);
474 for(int i = 0; i < memory_table.size; i++)
476 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
478 //printf("BC_Signals::unset_buffer %p\n", ptr);
479 clear_table_entry(&memory_table, i, 1);
480 pthread_mutex_unlock(lock);
485 pthread_mutex_unlock(lock);
486 // fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
504 // void* operator new(size_t size)
506 // //printf("new 1 %d\n", size);
507 // void *result = malloc(size);
508 // BUFFER(size, result, "new");
509 // //printf("new 2 %d\n", size);
513 // void* operator new[](size_t size)
515 // //printf("new [] 1 %d\n", size);
516 // void *result = malloc(size);
517 // BUFFER(size, result, "new []");
518 // //printf("new [] 2 %d\n", size);
522 // void operator delete(void *ptr)
524 // //printf("delete 1 %p\n", ptr);
526 // //printf("delete 2 %p\n", ptr);
530 // void operator delete[](void *ptr)
532 // //printf("delete [] 1 %p\n", ptr);
535 // //printf("delete [] 2 %p\n", ptr);