X-Git-Url: http://git.cinelerra-gg.org/git/?p=goodguy%2Fhistory.git;a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbcsignals.C;h=ed50cfb15d9e8ac38c630c3096c9ab2b77fce477;hp=e7c14074e9715ac69e4e2eae408f8f605fd9b08c;hb=7e5a0760f40ff787cc3d93cb7768a901ebe52809;hpb=bf87166cc5846f96c5be2621e329c1cbc21c1508 diff --git a/cinelerra-5.1/guicast/bcsignals.C b/cinelerra-5.1/guicast/bcsignals.C index e7c14074..ed50cfb1 100644 --- a/cinelerra-5.1/guicast/bcsignals.C +++ b/cinelerra-5.1/guicast/bcsignals.C @@ -24,6 +24,7 @@ #include "bccmodels.h" #include "bckeyboard.h" #include "bcresources.h" +#include "cstrdup.h" #include #include @@ -41,22 +42,6 @@ BC_Signals* BC_Signals::global_signals = 0; static int signal_done = 0; -static int table_id = 0; - -static bc_locktrace_t* new_bc_locktrace(void *ptr, - const char *title, - const char *location) -{ - bc_locktrace_t *result = (bc_locktrace_t*)malloc(sizeof(bc_locktrace_t)); - result->ptr = ptr; - result->title = title; - result->location = location; - result->is_owner = 0; - result->id = table_id++; - result->tid = pthread_self(); - return result; -} - static struct sigaction old_segv = {0, }, old_intr = {0, }; static void handle_dump(int n, siginfo_t * info, void *sc); @@ -103,30 +88,14 @@ void BC_Signals::set_catch_segv(bool v) { if( v == trap_sigsegv ) return; if( v ) catch_segv(); else uncatch_segv(); - v = trap_sigsegv; + trap_sigsegv = v; } void BC_Signals::set_catch_intr(bool v) { if( v == trap_sigintr ) return; if( v ) catch_intr(); else uncatch_intr(); - v = trap_sigintr; -} - -typedef struct -{ - int size; - void *ptr; - const char *location; -} bc_buffertrace_t; - -static bc_buffertrace_t* new_bc_buffertrace(int size, void *ptr, const char *location) -{ - bc_buffertrace_t *result = (bc_buffertrace_t*)malloc(sizeof(bc_buffertrace_t)); - result->size = size; - result->ptr = ptr; - result->location = location; - return result; + trap_sigintr = v; } static void bc_copy_textfile(int lines, FILE *ofp, const char *fmt,...) @@ -140,93 +109,55 @@ static void bc_copy_textfile(int lines, FILE *ofp, const char *fmt,...) fclose(ifp); } - -// Need our own table to avoid recursion with the memory manager -typedef struct -{ - void **values; - int size; - int allocation; -// This points to the next value to replace if the table wraps around - int current_value; -} bc_table_t; - -static void* append_table(bc_table_t *table, void *ptr) +static void bc_list_openfiles(int lines, FILE *ofp, const char *fmt,...) { - if(table->allocation <= table->size) - { - if(table->allocation) - { - int new_allocation = table->allocation * 2; - void **new_values = (void**)calloc(new_allocation, sizeof(void*)); - memcpy(new_values, table->values, sizeof(void*) * table->size); - free(table->values); - table->values = new_values; - table->allocation = new_allocation; - } - else - { - table->allocation = 4096; - table->values = (void**)calloc(table->allocation, sizeof(void*)); + va_list ap; va_start(ap, fmt); + char bfr[BCTEXTLEN]; vsnprintf(bfr, sizeof(bfr), fmt, ap); + va_end(ap); + DIR *dir = opendir(bfr); + if( !dir ) return; + struct dirent64 *dent; + while( --lines >= 0 && (dent = readdir64(dir)) ) { + const char *fn = dent->d_name; + fprintf(ofp, "%s", fn); + char path[BCTEXTLEN], link[BCTEXTLEN]; + struct stat st; + snprintf(path, sizeof(path), "%s/%s", bfr, fn); + if( !stat(path,&st) ) { + int typ = 0; + if( S_ISREG(st.st_mode) ) typ = ' '; + else if( S_ISDIR(st.st_mode) ) typ = 'd'; + else if( S_ISBLK(st.st_mode) ) typ = 'b'; + else if( S_ISCHR(st.st_mode) ) typ = 'c'; + else if( S_ISFIFO(st.st_mode) ) typ = 'f'; + else if( S_ISLNK(st.st_mode) ) typ = 'l'; + else if( S_ISSOCK(st.st_mode) ) typ = 's'; + if( typ ) fprintf(ofp, "\t%c", typ); + fprintf(ofp, "\tsize %jd", st.st_size); + int len = readlink(path, link, sizeof(link)-1); + if( len > 0 ) { + link[len] = 0; + fprintf(ofp, "\t-> %s", link); + } } - } - - table->values[table->size++] = ptr; - return ptr; -} - -// Replace item in table pointed to by current_value and advance -// current_value -static void* overwrite_table(bc_table_t *table, void *ptr) -{ - free(table->values[table->current_value]); - table->values[table->current_value++] = ptr; - if(table->current_value >= table->size) table->current_value = 0; - return 0; -} - -static void clear_table(bc_table_t *table, int delete_objects) -{ - if(delete_objects) - { - for(int i = 0; i < table->size; i++) - { - free(table->values[i]); + snprintf(path, sizeof(path), "%sinfo/%s", bfr, fn); + FILE *fp = fopen(path,"r"); int64_t pos; + if( fp ) { + while( fgets(link, sizeof(link), fp) ) { + if( sscanf(link, "pos:%jd", &pos) == 1 ) { + fprintf(ofp, "\tpos: %jd", pos); + break; + } + } + fclose(fp); } + fprintf(ofp, "\n"); } - table->size = 0; + closedir(dir); } -static void clear_table_entry(bc_table_t *table, int number, int delete_object) -{ - if(delete_object) free(table->values[number]); - for(int i = number; i < table->size - 1; i++) - { - table->values[i] = table->values[i + 1]; - } - table->size--; -} - -// Table of functions currently running. -static bc_table_t execution_table = { 0, 0, 0, 0 }; - -// Table of locked positions -static bc_table_t lock_table = { 0, 0, 0, 0 }; - -// Table of buffers -static bc_table_t memory_table = { 0, 0, 0, 0 }; - -static bc_table_t temp_files = { 0, 0, 0, 0 }; - // Can't use Mutex because it would be recursive -static pthread_mutex_t *lock = 0; static pthread_mutex_t *handler_lock = 0; -// incase lock set after task ends -static pthread_t last_lock_thread = 0; -static const char *last_lock_title = 0; -static const char *last_lock_location = 0; -// Don't trace memory until this is true to avoid initialization -static int trace_memory = 0; static const char* signal_titles[] = @@ -265,94 +196,45 @@ void BC_Signals::dump_stack(FILE *fp) void BC_Signals::kill_subs() { // List /proc directory - DIR *dirstream; struct dirent64 *new_filename; struct stat ostat; - char path[BCTEXTLEN]; - char string[BCTEXTLEN]; + char path[BCTEXTLEN], string[BCTEXTLEN]; + DIR *dirstream = opendir("/proc"); + if( !dirstream ) return; + pid_t ppid = getpid(); - dirstream = opendir("/proc"); - if(!dirstream) return; - - while( (new_filename = readdir64(dirstream)) != 0 ) - { -// All digits are numbers + while( (new_filename = readdir64(dirstream)) != 0 ) { char *ptr = new_filename->d_name; - int got_alpha = 0; - while(*ptr) - { - if(*ptr == '.' || isalpha(*ptr++)) - { - got_alpha = 1; - break; - } - } - - if(got_alpha) continue; + while( *ptr && *ptr != '.' && !isalpha(*ptr) ) ++ptr; +// All digits are numbers + if( *ptr ) continue; // Must be a directory sprintf(path, "/proc/%s", new_filename->d_name); - if(!stat(path, &ostat)) - { - if(S_ISDIR(ostat.st_mode)) - { -// Read process stat - strcat(path, "/stat"); -//printf("kill_subs %d %s\n", __LINE__, path); - FILE *fd = fopen(path, "r"); - -// Must search forwards because the file is 0 length - if(fd) - { - while(!feof(fd)) - { - char c = fgetc(fd); + if( stat(path, &ostat) ) continue; + if( !S_ISDIR(ostat.st_mode) ) continue; + strcat(path, "/stat"); + FILE *fd = fopen(path, "r"); + if( !fd ) continue; + while( !feof(fd) && fgetc(fd)!=')' ); //printf("kill_subs %d %d\n", __LINE__, c); - if(c == ')') - { -// Search for 2 spaces - int spaces = 0; - while(!feof(fd) && spaces < 2) - { - c = fgetc(fd); - if(c == ' ') - spaces++; - } - + for( int sp=2; !feof(fd) && sp>0; ) + if( fgetc(fd) == ' ' ) --sp; // Read in parent process - ptr = string; - while(!feof(fd)) - { - *ptr = fgetc(fd); - if(*ptr == ' ') - { - *ptr = 0; - break; - } - ptr++; - } + for( ptr=string; !feof(fd) && (*ptr=fgetc(fd))!=' '; ++ptr ); + if( (*ptr=fgetc(fd)) == ' ' ) break; + *ptr = 0; // printf("kill_subs %d process=%d getpid=%d parent_process=%d\n", -// __LINE__, -// atoi(new_filename->d_name), -// getpid(), -// atoi(string)); - int parent_process = atoi(string); - int child_process = atoi(new_filename->d_name); - +// __LINE__, atoi(new_filename->d_name), getpid(), atoi(string)); + int parent_process = atoi(string); // Kill if we're the parent - if(getpid() == parent_process) - { + if( ppid == parent_process ) { + int child_process = atoi(new_filename->d_name); //printf("kill_subs %d: process=%d\n", __LINE__, atoi(new_filename->d_name)); - kill(child_process, SIGKILL); - } - } - } - - fclose(fd); - } - } + kill(child_process, SIGKILL); } + fclose(fd); } } @@ -361,26 +243,19 @@ static void signal_entry(int signum) signal(signum, SIG_DFL); pthread_mutex_lock(handler_lock); - if(signal_done) - { - pthread_mutex_unlock(handler_lock); - exit(0); - } - + int done = signal_done; signal_done = 1; pthread_mutex_unlock(handler_lock); - + if( done ) exit(0); printf("signal_entry: got %s my pid=%d execution table size=%d:\n", - signal_titles[signum], - getpid(), - execution_table.size); + signal_titles[signum], getpid(), execution_table.size); BC_Signals::kill_subs(); - BC_Signals::dump_traces(); - BC_Signals::dump_locks(); - BC_Signals::dump_buffers(); - BC_Signals::delete_temps(); + BC_Trace::dump_traces(); + BC_Trace::dump_locks(); + BC_Trace::dump_buffers(); + BC_Trace::delete_temps(); // Call user defined signal handler BC_Signals::global_signals->signal_handler(signum); @@ -426,84 +301,6 @@ BC_Signals::~BC_Signals() BC_CModels::bcxfer_stop_slicers(); } -void BC_Signals::dump_traces(FILE *fp) -{ -// Dump trace table - if(execution_table.size) - { - for(int i = execution_table.current_value; i < execution_table.size; i++) - fprintf(fp," %s\n", (char*)execution_table.values[i]); - for(int i = 0; i < execution_table.current_value; i++) - fprintf(fp," %s\n", (char*)execution_table.values[i]); - } - -} - -void BC_Signals::dump_locks(FILE *fp) -{ -// Dump lock table -#ifdef TRACE_LOCKS - fprintf(fp,"signal_entry: lock table size=%d\n", lock_table.size); - for(int i = 0; i < lock_table.size; i++) - { - bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i]; - fprintf(fp," %p %s %s %p%s\n", table->ptr, - table->title, table->location, (void*)table->tid, - table->is_owner ? " *" : ""); - } -#endif -} - -void BC_Signals::dump_buffers(FILE *fp) -{ -#ifdef TRACE_MEMORY - pthread_mutex_lock(lock); -// Dump buffer table - fprintf(fp,"BC_Signals::dump_buffers: buffer table size=%d\n", memory_table.size); - for(int i = 0; i < memory_table.size; i++) - { - bc_buffertrace_t *entry = (bc_buffertrace_t*)memory_table.values[i]; - fprintf(fp," %d %p %s\n", entry->size, entry->ptr, entry->location); - } - pthread_mutex_unlock(lock); -#endif -} - -void BC_Signals::delete_temps() -{ - pthread_mutex_lock(lock); - if(temp_files.size) printf("BC_Signals::delete_temps: deleting %d temp files\n", temp_files.size); - for(int i = 0; i < temp_files.size; i++) - { - printf(" %s\n", (char*)temp_files.values[i]); - remove((char*)temp_files.values[i]); - } - pthread_mutex_unlock(lock); -} - -void BC_Signals::reset_locks() -{ - pthread_mutex_unlock(lock); -} - -void BC_Signals::set_temp(char *string) -{ - char *new_string = strdup(string); - append_table(&temp_files, new_string); -} - -void BC_Signals::unset_temp(char *string) -{ - for(int i = 0; i < temp_files.size; i++) - { - if(!strcmp((char*)temp_files.values[i], string)) - { - clear_table_entry(&temp_files, i, 1); - break; - } - } -} - int BC_Signals::x_error_handler(Display *display, XErrorEvent *event) { @@ -516,12 +313,12 @@ int BC_Signals::x_error_handler(Display *display, XErrorEvent *event) } -void BC_Signals::initialize() +void BC_Signals::initialize(const char *trap_path) { BC_Signals::global_signals = this; - lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t)); + BC_Trace::global_trace = this; + set_trap_path(trap_path); handler_lock = (pthread_mutex_t*)calloc(1, sizeof(pthread_mutex_t)); - pthread_mutex_init(lock, 0); pthread_mutex_init(handler_lock, 0); old_err_handler = XSetErrorHandler(x_error_handler); initialize2(); @@ -530,6 +327,7 @@ void BC_Signals::initialize() void BC_Signals::terminate() { BC_Signals::global_signals = 0; + BC_Trace::global_trace = 0; uncatch_segv(); uncatch_intr(); signal(SIGHUP, SIG_DFL); signal(SIGINT, SIG_DFL); @@ -541,15 +339,6 @@ void BC_Signals::terminate() XSetErrorHandler(old_err_handler); } -// callable from debugger -extern "C" -void dump() -{ - BC_Signals::dump_traces(); - BC_Signals::dump_locks(); - BC_Signals::dump_buffers(); -} - // kill SIGUSR2 void BC_Signals::signal_dump(int signum) { @@ -589,227 +378,6 @@ const char* BC_Signals::sig_to_str(int number) return signal_titles[number]; } -#define TOTAL_TRACES 16 - -void BC_Signals::new_trace(const char *text) -{ - if(!global_signals) return; - pthread_mutex_lock(lock); - -// Wrap around - if(execution_table.size >= TOTAL_TRACES) - { - overwrite_table(&execution_table, strdup(text)); -// clear_table(&execution_table, 1); - } - else - { - append_table(&execution_table, strdup(text)); - } - pthread_mutex_unlock(lock); -} - -void BC_Signals::new_trace(const char *file, const char *function, int line) -{ - char string[BCTEXTLEN]; - snprintf(string, BCTEXTLEN, "%s: %s: %d", file, function, line); - new_trace(string); -} - -void BC_Signals::delete_traces() -{ - if(!global_signals) return; - pthread_mutex_lock(lock); - clear_table(&execution_table, 0); - pthread_mutex_unlock(lock); -} - -// no canceling with lock held -void BC_Signals::lock_locks(const char *s) -{ - pthread_mutex_lock(lock); - last_lock_thread = pthread_self(); - last_lock_title = s; - last_lock_location = 0; -} - -void BC_Signals::unlock_locks() -{ - pthread_mutex_unlock(lock); -} - -#define TOTAL_LOCKS 256 - -int BC_Signals::set_lock(void *ptr, - const char *title, - const char *location) -{ - if(!global_signals) return 0; - bc_locktrace_t *table = 0; - int id_return = 0; - - pthread_mutex_lock(lock); - last_lock_thread = pthread_self(); - last_lock_title = title; - last_lock_location = location; - if(lock_table.size >= TOTAL_LOCKS) - clear_table(&lock_table, 0); - -// Put new lock entry - table = new_bc_locktrace(ptr, title, location); - append_table(&lock_table, table); - id_return = table->id; - - pthread_mutex_unlock(lock); - return id_return; -} - -void BC_Signals::set_lock2(int table_id) -{ - if(!global_signals) return; - - bc_locktrace_t *table = 0; - pthread_mutex_lock(lock); - for(int i = lock_table.size - 1; i >= 0; i--) - { - table = (bc_locktrace_t*)lock_table.values[i]; -// Got it. Hasn't been unlocked/deleted yet. - if(table->id == table_id) - { - table->is_owner = 1; - table->tid = pthread_self(); - pthread_mutex_unlock(lock); - return; - } - } - pthread_mutex_unlock(lock); -} - -void BC_Signals::unset_lock2(int table_id) -{ - if(!global_signals) return; - - bc_locktrace_t *table = 0; - pthread_mutex_lock(lock); - for(int i = lock_table.size - 1; i >= 0; i--) - { - table = (bc_locktrace_t*)lock_table.values[i]; - if(table->id == table_id) - { - clear_table_entry(&lock_table, i, 1); - break; - } - } - pthread_mutex_unlock(lock); -} - -void BC_Signals::unset_lock(void *ptr) -{ - if(!global_signals) return; - - bc_locktrace_t *table = 0; - pthread_mutex_lock(lock); - -// Take off currently held entry - for(int i = 0; i < lock_table.size; i++) - { - table = (bc_locktrace_t*)lock_table.values[i]; - if(table->ptr == ptr) - { - if(table->is_owner) - { - clear_table_entry(&lock_table, i, 1); - break; - } - } - } - - pthread_mutex_unlock(lock); -} - - -void BC_Signals::unset_all_locks(void *ptr) -{ - if(!global_signals) return; - pthread_mutex_lock(lock); -// Take off previous lock entry - for(int i = 0; i < lock_table.size; ) - { - bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i]; - if(table->ptr == ptr) - { - clear_table_entry(&lock_table, i, 1); - continue; - } - ++i; - } - pthread_mutex_unlock(lock); -} - -void BC_Signals::clear_locks_tid(pthread_t tid) -{ - if(!global_signals) return; - pthread_mutex_lock(lock); -// Take off previous lock entry - for(int i = 0; i < lock_table.size; ) - { - bc_locktrace_t *table = (bc_locktrace_t*)lock_table.values[i]; - if(table->tid == tid) - { - clear_table_entry(&lock_table, i, 1); - continue; - } - ++i; - } - pthread_mutex_unlock(lock); -} - - -void BC_Signals::enable_memory() -{ - trace_memory = 1; -} - -void BC_Signals::disable_memory() -{ - trace_memory = 0; -} - - -void BC_Signals::set_buffer(int size, void *ptr, const char* location) -{ - if(!global_signals) return; - if(!trace_memory) return; - -//printf("BC_Signals::set_buffer %p %s\n", ptr, location); - pthread_mutex_lock(lock); - append_table(&memory_table, new_bc_buffertrace(size, ptr, location)); - pthread_mutex_unlock(lock); -} - -int BC_Signals::unset_buffer(void *ptr) -{ - if(!global_signals) return 0; - if(!trace_memory) return 0; - - int ret = 1; - pthread_mutex_lock(lock); - for(int i = 0; i < memory_table.size; i++) - { - if(((bc_buffertrace_t*)memory_table.values[i])->ptr == ptr) - { -//printf("BC_Signals::unset_buffer %p\n", ptr); - clear_table_entry(&memory_table, i, 1); - ret = 0; - break; - } - } - - pthread_mutex_unlock(lock); -// fprintf(stderr, "BC_Signals::unset_buffer buffer %p not found.\n", ptr); - return ret; -} - #include #include @@ -833,7 +401,9 @@ static void handle_dump(int n, siginfo_t * info, void *sc) signal(SIGINT, SIG_DFL); // gotta be root, or the dump is worthless int uid = getuid(); - if( uid != 0 ) return; +// it is not necessary to be root if ptrace is allowed via: +// echo 0 > /proc/sys/kernel/yama/ptrace_scope (usually set to 1) +// if( uid != 0 ) return; ucontext_t *uc = (ucontext_t *)sc; int pid = getpid(), tid = gettid(); struct sigcontext *c = (struct sigcontext *)&uc->uc_mcontext; @@ -866,16 +436,19 @@ static void handle_dump(int n, siginfo_t * info, void *sc) } fprintf(fp,"\nCPUS: %d\n", BC_Resources::get_machine_cpus()); fprintf(fp,"\nCPUINFO:\n"); bc_copy_textfile(32, fp,"/proc/cpuinfo"); - fprintf(fp,"\nTHREADS:\n"); Thread::dump_threads(fp); - fprintf(fp,"\nTRACES:\n"); BC_Signals::dump_traces(fp); - fprintf(fp,"\nLOCKS:\n"); BC_Signals::dump_locks(fp); - fprintf(fp,"\nBUFFERS:\n"); BC_Signals::dump_buffers(fp); + fprintf(fp,"\nTHREADS:\n"); BC_Trace::dump_threads(fp); + fprintf(fp,"\nTRACES:\n"); BC_Trace::dump_traces(fp); + fprintf(fp,"\nLOCKS:\n"); BC_Trace::dump_locks(fp); + fprintf(fp,"\nBUFFERS:\n"); BC_Trace::dump_buffers(fp); + fprintf(fp,"\nSHMMEM:\n"); BC_Trace::dump_shm_stats(fp); if( BC_Signals::trap_hook ) { fprintf(fp,"\nMAIN HOOK:\n"); BC_Signals::trap_hook(fp, BC_Signals::trap_data); } fprintf(fp,"\nVERSION:\n"); bc_copy_textfile(INT_MAX, fp,"/proc/version"); fprintf(fp,"\nMEMINFO:\n"); bc_copy_textfile(INT_MAX, fp,"/proc/meminfo"); + fprintf(fp,"\nSTATUS:\n"); bc_copy_textfile(INT_MAX, fp,"/proc/%d/status",pid); + fprintf(fp,"\nFD:\n"); bc_list_openfiles(INT_MAX, fp,"/proc/%d/fd", pid); fprintf(fp,"\nMAPS:\n"); bc_copy_textfile(INT_MAX, fp,"/proc/%d/maps",pid); char proc_mem[64]; if( tid > 0 && tid != pid ) @@ -923,45 +496,3 @@ static void handle_dump(int n, siginfo_t * info, void *sc) execvp(argv[0], &argv[0]); } - - - - -#ifdef TRACE_MEMORY - -// void* operator new(size_t size) -// { -// //printf("new 1 %d\n", size); -// void *result = malloc(size); -// BUFFER(size, result, "new"); -// //printf("new 2 %d\n", size); -// return result; -// } -// -// void* operator new[](size_t size) -// { -// //printf("new [] 1 %d\n", size); -// void *result = malloc(size); -// BUFFER(size, result, "new []"); -// //printf("new [] 2 %d\n", size); -// return result; -// } -// -// void operator delete(void *ptr) -// { -// //printf("delete 1 %p\n", ptr); -// UNBUFFER(ptr); -// //printf("delete 2 %p\n", ptr); -// free(ptr); -// } -// -// void operator delete[](void *ptr) -// { -// //printf("delete [] 1 %p\n", ptr); -// UNBUFFER(ptr); -// free(ptr); -// //printf("delete [] 2 %p\n", ptr); -// } - - -#endif