r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / guicast / bcsignals.C
blob5009e8a4a3012770f02a576b6200bd69f5d8da88
1 #include "bcsignals.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
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, 
12         char *title, 
13         char *location)
15         bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t));
16         result->ptr = ptr;
17         result->title = title;
18         result->location = location;
19         result->is_owner = 0;
20         result->id = table_id++;
21         return result;
28 typedef struct
30         int size;
31         void *ptr;
32         char *location;
33 } bc_buffertrace_t;
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));
38         result->size = size;
39         result->ptr = ptr;
40         result->location = location;
41         return result;
49 // Need our own table to avoid recursion with the memory manager
50 typedef struct
52         void **values;
53         int size;
54         int allocation;
55 } bc_table_t;
57 static void* append_table(bc_table_t *table, void *ptr)
59         if(table->allocation <= table->size)
60         {
61                 if(table->allocation)
62                 {
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);
66                         free(table->values);
67                         table->values = new_values;
68                         table->allocation = new_allocation;
69                 }
70                 else
71                 {
72                         table->allocation = 4096;
73                         table->values = (void**)calloc(table->allocation, sizeof(void*));
74                 }
75         }
77         table->values[table->size++] = ptr;
78         return ptr;
81 static void clear_table(bc_table_t *table, int delete_objects)
83         if(delete_objects)
84         {
85                 for(int i = 0; i < table->size; i++)
86                 {
87                         free(table->values[i]);
88                 }
89         }
90         table->size = 0;
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++)
97         {
98                 table->values[i] = table->values[i + 1];
99         }
100         table->size--;
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 };
110 // Table of buffers
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[] =
124         "NULL",
125         "SIGHUP",
126         "SIGINT",
127         "SIGQUIT",
128         "SIGILL",
129         "SIGTRAP",
130         "SIGABRT",
131         "SIGBUS",
132         "SIGFPE",
133         "SIGKILL",
134         "SIGUSR1",
135         "SIGSEGV",
136         "SIGUSR2",
137         "SIGPIPE",
138         "SIGALRM",
139         "SIGTERM"
142 static void signal_entry(int signum)
144         signal(signum, SIG_DFL);
146         pthread_mutex_lock(handler_lock);
147         if(signal_done)
148         {
149                 pthread_mutex_unlock(handler_lock);
150                 exit(0);
151         }
153         signal_done = 1;
154         pthread_mutex_unlock(handler_lock);
157         printf("signal_entry: got %s my pid=%d execution table size=%d:\n", 
158                 signal_titles[signum],
159                 getpid(),
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);
170         exit(0);
173 BC_Signals::BC_Signals()
177 void BC_Signals::dump_traces()
179 // Dump trace table
180         if(execution_table.size)
181         {
182                 for(int i = 0; i < execution_table.size; i++)
183                         printf("    %s\n", execution_table.values[i]);
184         }
188 void BC_Signals::dump_locks()
190 // Dump lock table
191         printf("signal_entry: lock table size=%d\n", lock_table.size);
192         for(int i = 0; i < lock_table.size; i++)
193         {
194                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
195                 printf("    %p %s %s %s\n", 
196                         table->ptr,
197                         table->title,
198                         table->location,
199                         table->is_owner ? "*" : "");
200         }
204 void BC_Signals::dump_buffers()
206         pthread_mutex_lock(lock);
207 // Dump buffer table
208         printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
209         for(int i = 0; i < memory_table.size; i++)
210         {
211                 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
212                 printf("    %d %p %s\n", entry->size, entry->ptr, entry->location);
213         }
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++)
222         {
223                 printf("    %s\n", (char*)temp_files.values[i]);
224                 remove((char*)temp_files.values[i]);
225         }
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++)
238         {
239                 if(!strcmp((char*)temp_files.values[i], string))
240                 {
241                         clear_table_entry(&temp_files, i, 1);
242                         break;
243                 }
244         }
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);
256         initialize2();
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)
274 //      exit(0);
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, 
305         char *title, 
306         char *location)
308         if(!global_signals) return 0;
309         bc_locktrace_t *table = 0;
310         int id_return = 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);
322         return id_return;
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--)
332         {
333                 table = (bc_locktrace_t*)lock_table.values[i];
334 // Got it.  Hasn't been unlocked/deleted yet.
335                 if(table->id == table_id)
336                 {
337                         table->is_owner = 1;
338                         pthread_mutex_unlock(lock);
339                         return;
340                 }
341         }
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--)
352         {
353                 table = (bc_locktrace_t*)lock_table.values[i];
354                 if(table->id == table_id)
355                 {
356                         clear_table_entry(&lock_table, i, 1);
357                         pthread_mutex_unlock(lock);
358                         return;
359                 }
360         }
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++)
373         {
374                 table = (bc_locktrace_t*)lock_table.values[i];
375                 if(table->ptr == ptr)
376                 {
377                         if(table->is_owner)
378                         {
379                                 clear_table_entry(&lock_table, i, 1);
380                                 pthread_mutex_unlock(lock);
381                                 return;
382                         }
383                 }
384         }
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++)
396         {
397                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
398                 if(table->ptr == ptr)
399                 {
400                         clear_table_entry(&lock_table, i, 1);
401                 }
402         }
403         pthread_mutex_unlock(lock);
407 void BC_Signals::enable_memory()
409         trace_memory = 1;
412 void BC_Signals::disable_memory()
414         trace_memory = 0;
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++)
434         {
435                 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
436                 {
437                         clear_table_entry(&memory_table, i, 1);
438                         pthread_mutex_unlock(lock);
439                         return 0;
440                 }
441         }
442         pthread_mutex_unlock(lock);
443         fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
444         return 1;
459 #ifdef TRACE_MEMORY
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);
468         return result;
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);
477         return result;
480 void operator delete(void *ptr) 
482 //printf("delete 1 %p\n", ptr);
483         UNBUFFER(ptr);
484 //printf("delete 2 %p\n", ptr);
485     free(ptr);
488 void operator delete[](void *ptr) 
490 //printf("delete [] 1 %p\n", ptr);
491         UNBUFFER(ptr);
492     free(ptr);
493 //printf("delete [] 2 %p\n", ptr);
497 #endif