Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bcsignals.C

Go to the documentation of this file.
00001 #include "bcsignals.h"
00002 #include "bcwindowbase.inc"
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <unistd.h>
00007 
00008 BC_Signals* BC_Signals::global_signals = 0;
00009 static int signal_done = 0;
00010 static int table_id = 0;
00011 
00012 static bc_locktrace_t* new_bc_locktrace(void *ptr, 
00013         char *title, 
00014         char *location)
00015 {
00016         bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t));
00017         result->ptr = ptr;
00018         result->title = title;
00019         result->location = location;
00020         result->is_owner = 0;
00021         result->id = table_id++;
00022         return result;
00023 }
00024 
00025 
00026 
00027 
00028 
00029 typedef struct
00030 {
00031         int size;
00032         void *ptr;
00033         char *location;
00034 } bc_buffertrace_t;
00035 
00036 static bc_buffertrace_t* new_bc_buffertrace(int size, void *ptr, char *location)
00037 {
00038         bc_buffertrace_t *result = (bc_buffertrace_t*)malloc(sizeof(bc_buffertrace_t));
00039         result->size = size;
00040         result->ptr = ptr;
00041         result->location = location;
00042         return result;
00043 }
00044 
00045 
00046 
00047 
00048 
00049 
00050 // Need our own table to avoid recursion with the memory manager
00051 typedef struct
00052 {
00053         void **values;
00054         int size;
00055         int allocation;
00056 } bc_table_t;
00057 
00058 static void* append_table(bc_table_t *table, void *ptr)
00059 {
00060         if(table->allocation <= table->size)
00061         {
00062                 if(table->allocation)
00063                 {
00064                         int new_allocation = table->allocation * 2;
00065                         void **new_values = (void**)calloc(new_allocation, sizeof(void*));
00066                         memcpy(new_values, table->values, sizeof(void*) * table->size);
00067                         free(table->values);
00068                         table->values = new_values;
00069                         table->allocation = new_allocation;
00070                 }
00071                 else
00072                 {
00073                         table->allocation = 4096;
00074                         table->values = (void**)calloc(table->allocation, sizeof(void*));
00075                 }
00076         }
00077 
00078         table->values[table->size++] = ptr;
00079         return ptr;
00080 }
00081 
00082 static void clear_table(bc_table_t *table, int delete_objects)
00083 {
00084         if(delete_objects)
00085         {
00086                 for(int i = 0; i < table->size; i++)
00087                 {
00088                         free(table->values[i]);
00089                 }
00090         }
00091         table->size = 0;
00092 }
00093 
00094 static void clear_table_entry(bc_table_t *table, int number, int delete_object)
00095 {
00096         if(delete_object) free(table->values[number]);
00097         for(int i = number; i < table->size - 1; i++)
00098         {
00099                 table->values[i] = table->values[i + 1];
00100         }
00101         table->size--;
00102 }
00103 
00104 
00105 // Table of functions currently running.
00106 static bc_table_t execution_table = { 0, 0, 0 };
00107 
00108 // Table of locked positions
00109 static bc_table_t lock_table = { 0, 0, 0 };
00110 
00111 // Table of buffers
00112 static bc_table_t memory_table = { 0, 0, 0 };
00113 
00114 static bc_table_t temp_files = { 0, 0, 0 };
00115 
00116 // Can't use Mutex because it would be recursive
00117 static pthread_mutex_t *lock = 0;
00118 static pthread_mutex_t *handler_lock = 0;
00119 // Don't trace memory until this is true to avoid initialization
00120 static int trace_memory = 0;
00121 
00122 
00123 static char* signal_titles[] =
00124 {
00125         "NULL",
00126         "SIGHUP",
00127         "SIGINT",
00128         "SIGQUIT",
00129         "SIGILL",
00130         "SIGTRAP",
00131         "SIGABRT",
00132         "SIGBUS",
00133         "SIGFPE",
00134         "SIGKILL",
00135         "SIGUSR1",
00136         "SIGSEGV",
00137         "SIGUSR2",
00138         "SIGPIPE",
00139         "SIGALRM",
00140         "SIGTERM"
00141 };
00142 
00143 static void signal_entry(int signum)
00144 {
00145         signal(signum, SIG_DFL);
00146 
00147         pthread_mutex_lock(handler_lock);
00148         if(signal_done)
00149         {
00150                 pthread_mutex_unlock(handler_lock);
00151                 exit(0);
00152         }
00153 
00154         signal_done = 1;
00155         pthread_mutex_unlock(handler_lock);
00156 
00157 
00158         printf("signal_entry: got %s my pid=%d execution table size=%d:\n", 
00159                 signal_titles[signum],
00160                 getpid(),
00161                 execution_table.size);
00162 
00163         BC_Signals::dump_traces();
00164         BC_Signals::dump_locks();
00165         BC_Signals::dump_buffers();
00166         BC_Signals::delete_temps();
00167 
00168 // Call user defined signal handler
00169         BC_Signals::global_signals->signal_handler(signum);
00170 
00171         exit(0);
00172 }
00173 
00174 static void signal_entry_recoverable(int signum)
00175 {
00176         printf("signal_entry_recoverable: got %s my pid=%d\n", 
00177                 signal_titles[signum],
00178                 getpid());
00179 }
00180 
00181 BC_Signals::BC_Signals()
00182 {
00183 }
00184 
00185 void BC_Signals::dump_traces()
00186 {
00187 // Dump trace table
00188         if(execution_table.size)
00189         {
00190                 for(int i = 0; i < execution_table.size; i++)
00191                         printf("    %s\n", execution_table.values[i]);
00192         }
00193 
00194 }
00195 
00196 void BC_Signals::dump_locks()
00197 {
00198 // Dump lock table
00199         printf("signal_entry: lock table size=%d\n", lock_table.size);
00200         for(int i = 0; i < lock_table.size; i++)
00201         {
00202                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
00203                 printf("    %p %s %s %s\n", 
00204                         table->ptr,
00205                         table->title,
00206                         table->location,
00207                         table->is_owner ? "*" : "");
00208         }
00209 
00210 }
00211 
00212 void BC_Signals::dump_buffers()
00213 {
00214         pthread_mutex_lock(lock);
00215 // Dump buffer table
00216         printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
00217         for(int i = 0; i < memory_table.size; i++)
00218         {
00219                 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
00220                 printf("    %d %p %s\n", entry->size, entry->ptr, entry->location);
00221         }
00222         pthread_mutex_unlock(lock);
00223 }
00224 
00225 void BC_Signals::delete_temps()
00226 {
00227         pthread_mutex_lock(lock);
00228         printf("BC_Signals::delete_temps: deleting %d temp files\n", temp_files.size);
00229         for(int i = 0; i < temp_files.size; i++)
00230         {
00231                 printf("    %s\n", (char*)temp_files.values[i]);
00232                 remove((char*)temp_files.values[i]);
00233         }
00234         pthread_mutex_unlock(lock);
00235 }
00236 
00237 void BC_Signals::set_temp(char *string)
00238 {
00239         char *new_string = strdup(string);
00240         append_table(&temp_files, new_string);
00241 }
00242 
00243 void BC_Signals::unset_temp(char *string)
00244 {
00245         for(int i = 0; i < temp_files.size; i++)
00246         {
00247                 if(!strcmp((char*)temp_files.values[i], string))
00248                 {
00249                         clear_table_entry(&temp_files, i, 1);
00250                         break;
00251                 }
00252         }
00253 }
00254 
00255 
00256 void BC_Signals::initialize()
00257 {
00258         BC_Signals::global_signals = this;
00259         lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
00260         handler_lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t));
00261         pthread_mutex_init(lock, 0);
00262         pthread_mutex_init(handler_lock, 0);
00263 
00264         initialize2();
00265 }
00266 
00267 
00268 void BC_Signals::initialize2()
00269 {
00270         signal(SIGHUP, signal_entry);
00271         signal(SIGINT, signal_entry);
00272         signal(SIGQUIT, signal_entry);
00273         // SIGKILL cannot be stopped
00274         // signal(SIGKILL, signal_entry);
00275         signal(SIGSEGV, signal_entry);
00276         signal(SIGTERM, signal_entry);
00277         signal(SIGFPE, signal_entry_recoverable);
00278         signal(SIGPIPE, signal_entry_recoverable);
00279 }
00280 
00281 
00282 void BC_Signals::signal_handler(int signum)
00283 {
00284 printf("BC_Signals::signal_handler\n");
00285 //      exit(0);
00286 }
00287 
00288 char* BC_Signals::sig_to_str(int number)
00289 {
00290         return signal_titles[number];
00291 }
00292 
00293 #define TOTAL_TRACES 100
00294 
00295 void BC_Signals::new_trace(char *text)
00296 {
00297         if(!global_signals) return;
00298         pthread_mutex_lock(lock);
00299         if(execution_table.size >= TOTAL_TRACES)
00300                 clear_table(&execution_table, 1);
00301         append_table(&execution_table, strdup(text));
00302         pthread_mutex_unlock(lock);
00303 }
00304 
00305 void BC_Signals::new_trace(const char *file, const char *function, int line)
00306 {
00307         char string[BCTEXTLEN];
00308         snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line);
00309         new_trace(string);
00310 }
00311 
00312 void BC_Signals::delete_traces()
00313 {
00314         if(!global_signals) return;
00315         pthread_mutex_lock(lock);
00316         clear_table(&execution_table, 0);
00317         pthread_mutex_unlock(lock);
00318 }
00319 
00320 #define TOTAL_LOCKS 100
00321 
00322 int BC_Signals::set_lock(void *ptr, 
00323         char *title, 
00324         char *location)
00325 {
00326         if(!global_signals) return 0;
00327         bc_locktrace_t *table = 0;
00328         int id_return = 0;
00329 
00330         pthread_mutex_lock(lock);
00331         if(lock_table.size >= TOTAL_LOCKS)
00332                 clear_table(&lock_table, 0);
00333 
00334 // Put new lock entry
00335         table = new_bc_locktrace(ptr, title, location);
00336         append_table(&lock_table, table);
00337         id_return = table->id;
00338 
00339         pthread_mutex_unlock(lock);
00340         return id_return;
00341 }
00342 
00343 void BC_Signals::set_lock2(int table_id)
00344 {
00345         if(!global_signals) return;
00346 
00347         bc_locktrace_t *table = 0;
00348         pthread_mutex_lock(lock);
00349         for(int i = lock_table.size - 1; i >= 0; i--)
00350         {
00351                 table = (bc_locktrace_t*)lock_table.values[i];
00352 // Got it.  Hasn't been unlocked/deleted yet.
00353                 if(table->id == table_id)
00354                 {
00355                         table->is_owner = 1;
00356                         pthread_mutex_unlock(lock);
00357                         return;
00358                 }
00359         }
00360         pthread_mutex_unlock(lock);
00361 }
00362 
00363 void BC_Signals::unset_lock2(int table_id)
00364 {
00365         if(!global_signals) return;
00366 
00367         bc_locktrace_t *table = 0;
00368         pthread_mutex_lock(lock);
00369         for(int i = lock_table.size - 1; i >= 0; i--)
00370         {
00371                 table = (bc_locktrace_t*)lock_table.values[i];
00372                 if(table->id == table_id)
00373                 {
00374                         clear_table_entry(&lock_table, i, 1);
00375                         pthread_mutex_unlock(lock);
00376                         return;
00377                 }
00378         }
00379         pthread_mutex_unlock(lock);
00380 }
00381 
00382 void BC_Signals::unset_lock(void *ptr)
00383 {
00384         if(!global_signals) return;
00385 
00386         bc_locktrace_t *table = 0;
00387         pthread_mutex_lock(lock);
00388 
00389 // Take off currently held entry
00390         for(int i = 0; i < lock_table.size; i++)
00391         {
00392                 table = (bc_locktrace_t*)lock_table.values[i];
00393                 if(table->ptr == ptr)
00394                 {
00395                         if(table->is_owner)
00396                         {
00397                                 clear_table_entry(&lock_table, i, 1);
00398                                 pthread_mutex_unlock(lock);
00399                                 return;
00400                         }
00401                 }
00402         }
00403 
00404         pthread_mutex_unlock(lock);
00405 }
00406 
00407 
00408 void BC_Signals::unset_all_locks(void *ptr)
00409 {
00410         if(!global_signals) return;
00411         pthread_mutex_lock(lock);
00412 // Take off previous lock entry
00413         for(int i = 0; i < lock_table.size; i++)
00414         {
00415                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
00416                 if(table->ptr == ptr)
00417                 {
00418                         clear_table_entry(&lock_table, i, 1);
00419                 }
00420         }
00421         pthread_mutex_unlock(lock);
00422 }
00423 
00424 
00425 void BC_Signals::enable_memory()
00426 {
00427         trace_memory = 1;
00428 }
00429 
00430 void BC_Signals::disable_memory()
00431 {
00432         trace_memory = 0;
00433 }
00434 
00435 
00436 void BC_Signals::set_buffer(int size, void *ptr, char* location)
00437 {
00438         if(!global_signals) return;
00439         if(!trace_memory) return;
00440 
00441         pthread_mutex_lock(lock);
00442         append_table(&memory_table, new_bc_buffertrace(size, ptr, location));
00443         pthread_mutex_unlock(lock);
00444 }
00445 
00446 int BC_Signals::unset_buffer(void *ptr)
00447 {
00448         if(!global_signals) return 0;
00449         if(!trace_memory) return 0;
00450         pthread_mutex_lock(lock);
00451         for(int i = 0; i < memory_table.size; i++)
00452         {
00453                 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
00454                 {
00455                         clear_table_entry(&memory_table, i, 1);
00456                         pthread_mutex_unlock(lock);
00457                         return 0;
00458                 }
00459         }
00460         pthread_mutex_unlock(lock);
00461         fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
00462         return 1;
00463 }
00464 
00465 
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 #ifdef TRACE_MEMORY
00478 
00479 // Vice president of memory management
00480 void* operator new(size_t size) 
00481 {
00482 //printf("new 1 %d\n", size);
00483     void *result = malloc(size);
00484         BUFFER(size, result, "new");
00485 //printf("new 2 %d\n", size);
00486         return result;
00487 }
00488 
00489 void* operator new[](size_t size) 
00490 {
00491 //printf("new [] 1 %d\n", size);
00492     void *result = malloc(size);
00493         BUFFER(size, result, "new []");
00494 //printf("new [] 2 %d\n", size);
00495         return result;
00496 }
00497 
00498 void operator delete(void *ptr) 
00499 {
00500 //printf("delete 1 %p\n", ptr);
00501         UNBUFFER(ptr);
00502 //printf("delete 2 %p\n", ptr);
00503     free(ptr);
00504 }
00505 
00506 void operator delete[](void *ptr) 
00507 {
00508 //printf("delete [] 1 %p\n", ptr);
00509         UNBUFFER(ptr);
00510     free(ptr);
00511 //printf("delete [] 2 %p\n", ptr);
00512 }
00513 
00514 
00515 #endif

Generated on Sun Jan 8 13:26:33 2006 for Guicast-svn by  doxygen 1.4.4