r701: Jean-Luc Coulon has gettextized [tm] 2 more strings in the time average effect.
[cinelerra_cv.git] / guicast / bcsignals.C
blob047b28fdd299ac019f675b97a2fbad732d643fe5
1 #include "bcsignals.h"
2 #include "bcwindowbase.inc"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
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, 
13         char *title, 
14         char *location)
16         bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t));
17         result->ptr = ptr;
18         result->title = title;
19         result->location = location;
20         result->is_owner = 0;
21         result->id = table_id++;
22         return result;
29 typedef struct
31         int size;
32         void *ptr;
33         char *location;
34 } bc_buffertrace_t;
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));
39         result->size = size;
40         result->ptr = ptr;
41         result->location = location;
42         return result;
50 // Need our own table to avoid recursion with the memory manager
51 typedef struct
53         void **values;
54         int size;
55         int allocation;
56 } bc_table_t;
58 static void* append_table(bc_table_t *table, void *ptr)
60         if(table->allocation <= table->size)
61         {
62                 if(table->allocation)
63                 {
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);
67                         free(table->values);
68                         table->values = new_values;
69                         table->allocation = new_allocation;
70                 }
71                 else
72                 {
73                         table->allocation = 4096;
74                         table->values = (void**)calloc(table->allocation, sizeof(void*));
75                 }
76         }
78         table->values[table->size++] = ptr;
79         return ptr;
82 static void clear_table(bc_table_t *table, int delete_objects)
84         if(delete_objects)
85         {
86                 for(int i = 0; i < table->size; i++)
87                 {
88                         free(table->values[i]);
89                 }
90         }
91         table->size = 0;
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++)
98         {
99                 table->values[i] = table->values[i + 1];
100         }
101         table->size--;
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 };
111 // Table of buffers
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[] =
125         "NULL",
126         "SIGHUP",
127         "SIGINT",
128         "SIGQUIT",
129         "SIGILL",
130         "SIGTRAP",
131         "SIGABRT",
132         "SIGBUS",
133         "SIGFPE",
134         "SIGKILL",
135         "SIGUSR1",
136         "SIGSEGV",
137         "SIGUSR2",
138         "SIGPIPE",
139         "SIGALRM",
140         "SIGTERM"
143 static void signal_entry(int signum)
145         signal(signum, SIG_DFL);
147         pthread_mutex_lock(handler_lock);
148         if(signal_done)
149         {
150                 pthread_mutex_unlock(handler_lock);
151                 exit(0);
152         }
154         signal_done = 1;
155         pthread_mutex_unlock(handler_lock);
158         printf("signal_entry: got %s my pid=%d execution table size=%d:\n", 
159                 signal_titles[signum],
160                 getpid(),
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);
171         exit(0);
174 static void signal_entry_recoverable(int signum)
176         printf("signal_entry_recoverable: got %s my pid=%d\n", 
177                 signal_titles[signum],
178                 getpid());
181 BC_Signals::BC_Signals()
185 void BC_Signals::dump_traces()
187 // Dump trace table
188         if(execution_table.size)
189         {
190                 for(int i = 0; i < execution_table.size; i++)
191                         printf("    %s\n", execution_table.values[i]);
192         }
196 void BC_Signals::dump_locks()
198 // Dump lock table
199         printf("signal_entry: lock table size=%d\n", lock_table.size);
200         for(int i = 0; i < lock_table.size; i++)
201         {
202                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
203                 printf("    %p %s %s %s\n", 
204                         table->ptr,
205                         table->title,
206                         table->location,
207                         table->is_owner ? "*" : "");
208         }
212 void BC_Signals::dump_buffers()
214         pthread_mutex_lock(lock);
215 // Dump buffer table
216         printf("BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size);
217         for(int i = 0; i < memory_table.size; i++)
218         {
219                 bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i];
220                 printf("    %d %p %s\n", entry->size, entry->ptr, entry->location);
221         }
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++)
230         {
231                 printf("    %s\n", (char*)temp_files.values[i]);
232                 remove((char*)temp_files.values[i]);
233         }
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++)
246         {
247                 if(!strcmp((char*)temp_files.values[i], string))
248                 {
249                         clear_table_entry(&temp_files, i, 1);
250                         break;
251                 }
252         }
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);
264         initialize2();
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");
285 //      exit(0);
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);
309         new_trace(string);
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, 
323         char *title, 
324         char *location)
326         if(!global_signals) return 0;
327         bc_locktrace_t *table = 0;
328         int id_return = 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);
340         return id_return;
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--)
350         {
351                 table = (bc_locktrace_t*)lock_table.values[i];
352 // Got it.  Hasn't been unlocked/deleted yet.
353                 if(table->id == table_id)
354                 {
355                         table->is_owner = 1;
356                         pthread_mutex_unlock(lock);
357                         return;
358                 }
359         }
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--)
370         {
371                 table = (bc_locktrace_t*)lock_table.values[i];
372                 if(table->id == table_id)
373                 {
374                         clear_table_entry(&lock_table, i, 1);
375                         pthread_mutex_unlock(lock);
376                         return;
377                 }
378         }
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++)
391         {
392                 table = (bc_locktrace_t*)lock_table.values[i];
393                 if(table->ptr == ptr)
394                 {
395                         if(table->is_owner)
396                         {
397                                 clear_table_entry(&lock_table, i, 1);
398                                 pthread_mutex_unlock(lock);
399                                 return;
400                         }
401                 }
402         }
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++)
414         {
415                 bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i];
416                 if(table->ptr == ptr)
417                 {
418                         clear_table_entry(&lock_table, i, 1);
419                 }
420         }
421         pthread_mutex_unlock(lock);
425 void BC_Signals::enable_memory()
427         trace_memory = 1;
430 void BC_Signals::disable_memory()
432         trace_memory = 0;
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++)
452         {
453                 if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr)
454                 {
455                         clear_table_entry(&memory_table, i, 1);
456                         pthread_mutex_unlock(lock);
457                         return 0;
458                 }
459         }
460         pthread_mutex_unlock(lock);
461         fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr);
462         return 1;
477 #ifdef TRACE_MEMORY
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);
486         return result;
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);
495         return result;
498 void operator delete(void *ptr) 
500 //printf("delete 1 %p\n", ptr);
501         UNBUFFER(ptr);
502 //printf("delete 2 %p\n", ptr);
503     free(ptr);
506 void operator delete[](void *ptr) 
508 //printf("delete [] 1 %p\n", ptr);
509         UNBUFFER(ptr);
510     free(ptr);
511 //printf("delete [] 2 %p\n", ptr);
515 #endif