7 BC_Signals* BC_Signals::global_signals = 0;
8 static int signal_done = 0;
9 static int table_id = 0;
11 static bc_locktrace_t* new_bc_locktrace(void *ptr,
15 bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t));
17 result->title = title;
18 result->location = location;
20 result->id = table_id++;
35 static bc_buffertrace_t* new_bc_buffertrace(int size, void *ptr, char *location)
37 bc_buffertrace_t *result = (bc_buffertrace_t*)malloc(sizeof(bc_buffertrace_t));
40 result->location = location;
49 // Need our own table to avoid recursion with the memory manager
57 static void* append_table(bc_table_t *table, void *ptr)
59 if(table->allocation <= table->size)
63 int new_allocation = table->allocation * 2;
64 void **new_values = (void**)calloc(new_allocation, sizeof(void*));
65 memcpy(new_values, table->values, sizeof(void*) * table->size);
67 table->values = new_values;
68 table->allocation = new_allocation;
72 table->allocation = 4096;
73 table->values = (void**)calloc(table->allocation, sizeof(void*));
77 table->values[table->size++] = ptr;
81 static void clear_table(bc_table_t *table, int delete_objects)
85 for(int i = 0; i < table->size; i++)
87 free(table->values[i]);
93 static void clear_table_entry(bc_table_t *table, int number, int delete_object)
95 if(delete_object) free(table->values[number]);
96 for(int i = number; i < table->size - 1; i++)
98 table->values[i] = table->values[i + 1];
104 // Table of functions currently running.
105 static bc_table_t execution_table = { 0, 0, 0 };
107 // Table of locked positions
108 static bc_table_t lock_table = { 0, 0, 0 };
111 static bc_table_t memory_table = { 0, 0, 0 };
113 static bc_table_t temp_files = { 0, 0, 0 };
115 // Can't use Mutex because it would be recursive
116 static pthread_mutex_t *lock = 0;
117 static pthread_mutex_t *handler_lock = 0;
118 // Don't trace memory until this is true to avoid initialization
119 static int trace_memory = 0;
122 static char* signal_titles[] =
142 static void signal_entry(int signum)
144 signal(signum, SIG_DFL);
146 pthread_mutex_lock(handler_lock);
149 pthread_mutex_unlock(handler_lock);
154 pthread_mutex_unlock(handler_lock);
157 printf("signal_entry: got %s my pid=%d execution table size=%d:\n",
158 signal_titles[signum],
160 execution_table.size);
162 BC_Signals::dump_traces();
163 BC_Signals::dump_locks();
164 BC_Signals::dump_buffers();
165 BC_Signals::delete_temps();
167 // Call user defined signal handler
168 BC_Signals::global_signals->signal_handler(signum);
173 BC_Signals::BC_Signals()
177 void BC_Signals::dump_traces()
180 if(execution_table.size)
182 for(int i = 0; i < execution_table.size; i++)
183 printf(" %s\n", execution_table.values[i]);
188 void BC_Signals::dump_locks()
191 printf("signal_entry: lock table size=%d\n", lock_table.size);
192 for(int i = 0; i < lock_table.size; i++)
194 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
195 printf(" %p %s %s %s\n",
199 table->is_owner ? "*" : "");
204 void BC_Signals::dump_buffers()
206 pthread_mutex_lock(lock);
208 printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
209 for(int i = 0; i < memory_table.size; i++)
211 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
212 printf(" %d %p %s\n", entry->size, entry->ptr, entry->location);
214 pthread_mutex_unlock(lock);
217 void BC_Signals::delete_temps()
219 pthread_mutex_lock(lock);
220 printf("BC_Signals::delete_temps: deleting %d temp files\n", temp_files.size);
221 for(int i = 0; i < temp_files.size; i++)
223 printf(" %s\n", (char*)temp_files.values[i]);
224 remove((char*)temp_files.values[i]);
226 pthread_mutex_unlock(lock);
229 void BC_Signals::set_temp(char *string)
231 char *new_string = strdup(string);
232 append_table(&temp_files, new_string);
235 void BC_Signals::unset_temp(char *string)
237 for(int i = 0; i < temp_files.size; i++)
239 if(!strcmp((char*)temp_files.values[i], string))
241 clear_table_entry(&temp_files, i, 1);
248 void BC_Signals::initialize()
250 BC_Signals::global_signals = this;
251 lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
252 handler_lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
253 pthread_mutex_init(lock, 0);
254 pthread_mutex_init(handler_lock, 0);
260 void BC_Signals::initialize2()
262 signal(SIGHUP, signal_entry);
263 signal(SIGINT, signal_entry);
264 signal(SIGQUIT, signal_entry);
265 signal(SIGKILL, signal_entry);
266 signal(SIGSEGV, signal_entry);
267 signal(SIGTERM, signal_entry);
268 signal(SIGFPE, signal_entry);
272 void BC_Signals::signal_handler(int signum)
277 char* BC_Signals::sig_to_str(int number)
279 return signal_titles[number];
282 #define TOTAL_TRACES 100
284 void BC_Signals::new_trace(char *text)
286 if(!global_signals) return;
287 pthread_mutex_lock(lock);
288 if(execution_table.size >= TOTAL_TRACES)
289 clear_table(&execution_table, 0);
290 append_table(&execution_table, text);
291 pthread_mutex_unlock(lock);
294 void BC_Signals::delete_traces()
296 if(!global_signals) return;
297 pthread_mutex_lock(lock);
298 clear_table(&execution_table, 0);
299 pthread_mutex_unlock(lock);
302 #define TOTAL_LOCKS 100
304 int BC_Signals::set_lock(void *ptr,
308 if(!global_signals) return 0;
309 bc_locktrace_t *table = 0;
312 pthread_mutex_lock(lock);
313 if(lock_table.size >= TOTAL_LOCKS)
314 clear_table(&lock_table, 0);
316 // Put new lock entry
317 table = new_bc_locktrace(ptr, title, location);
318 append_table(&lock_table, table);
319 id_return = table->id;
321 pthread_mutex_unlock(lock);
325 void BC_Signals::set_lock2(int table_id)
327 if(!global_signals) return;
329 bc_locktrace_t *table = 0;
330 pthread_mutex_lock(lock);
331 for(int i = lock_table.size - 1; i >= 0; i--)
333 table = (bc_locktrace_t*)lock_table.values[i];
334 // Got it. Hasn't been unlocked/deleted yet.
335 if(table->id == table_id)
338 pthread_mutex_unlock(lock);
342 pthread_mutex_unlock(lock);
345 void BC_Signals::unset_lock2(int table_id)
347 if(!global_signals) return;
349 bc_locktrace_t *table = 0;
350 pthread_mutex_lock(lock);
351 for(int i = lock_table.size - 1; i >= 0; i--)
353 table = (bc_locktrace_t*)lock_table.values[i];
354 if(table->id == table_id)
356 clear_table_entry(&lock_table, i, 1);
357 pthread_mutex_unlock(lock);
361 pthread_mutex_unlock(lock);
364 void BC_Signals::unset_lock(void *ptr)
366 if(!global_signals) return;
368 bc_locktrace_t *table = 0;
369 pthread_mutex_lock(lock);
371 // Take off currently held entry
372 for(int i = 0; i < lock_table.size; i++)
374 table = (bc_locktrace_t*)lock_table.values[i];
375 if(table->ptr == ptr)
379 clear_table_entry(&lock_table, i, 1);
380 pthread_mutex_unlock(lock);
386 pthread_mutex_unlock(lock);
390 void BC_Signals::unset_all_locks(void *ptr)
392 if(!global_signals) return;
393 pthread_mutex_lock(lock);
394 // Take off previous lock entry
395 for(int i = 0; i < lock_table.size; i++)
397 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
398 if(table->ptr == ptr)
400 clear_table_entry(&lock_table, i, 1);
403 pthread_mutex_unlock(lock);
407 void BC_Signals::enable_memory()
412 void BC_Signals::disable_memory()
418 void BC_Signals::set_buffer(int size, void *ptr, char* location)
420 if(!global_signals) return;
421 if(!trace_memory) return;
423 pthread_mutex_lock(lock);
424 append_table(&memory_table, new_bc_buffertrace(size, ptr, location));
425 pthread_mutex_unlock(lock);
428 int BC_Signals::unset_buffer(void *ptr)
430 if(!global_signals) return 0;
431 if(!trace_memory) return 0;
432 pthread_mutex_lock(lock);
433 for(int i = 0; i < memory_table.size; i++)
435 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
437 clear_table_entry(&memory_table, i, 1);
438 pthread_mutex_unlock(lock);
442 pthread_mutex_unlock(lock);
443 fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
461 // Vice president of memory management
462 void* operator new(size_t size)
464 //printf("new 1 %d\n", size);
465 void *result = malloc(size);
466 BUFFER(size, result, "new");
467 //printf("new 2 %d\n", size);
471 void* operator new[](size_t size)
473 //printf("new [] 1 %d\n", size);
474 void *result = malloc(size);
475 BUFFER(size, result, "new []");
476 //printf("new [] 2 %d\n", size);
480 void operator delete(void *ptr)
482 //printf("delete 1 %p\n", ptr);
484 //printf("delete 2 %p\n", ptr);
488 void operator delete[](void *ptr)
490 //printf("delete [] 1 %p\n", ptr);
493 //printf("delete [] 2 %p\n", ptr);