/* * CINELERRA * Copyright (C) 1997-2014 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ // debugging functions go here #ifndef BCSIGNALS_H #define BCSIGNALS_H #include "arraylist.h" #include "bcsignals.inc" #include #include #include #include #define TRON(x) BC_Signals::new_function(x); #define TROFF(x) BC_Signals::delete_function(x); // BC_Signals must be initialized at the start of every program using // debugging. //#define ENABLE_TRACE #define TRACE_LOCKS //#ifdef TRACE_LOCKS //#undef TRACE_LOCKS //#endif //#define TRACE_MEMORY // Need to use structs to avoid the memory manager. // One of these tables is created every time someone locks a lock. // After successfully locking, the table is flagged as being the owner of the lock. // In the unlock function, the table flagged as the owner of the lock is deleted. typedef struct { void *ptr; const char *title; const char *location; int is_owner; int id; pthread_t tid; } bc_locktrace_t; class BC_Signals { int (*old_err_handler)(Display *, XErrorEvent *); static int x_error_handler(Display *display, XErrorEvent *event); public: BC_Signals(); void initialize(); void initialize2(); void terminate(); virtual void signal_handler(int signum); static void dump_stack(FILE *fp=stdout); #ifdef ENABLE_TRACE // Add a trace #define TRACE(text) BC_Signals::new_trace(text); #define SET_TRACE BC_Signals::new_trace(__FILE__, __FUNCTION__, __LINE__); #define PRINT_TRACE { printf("%s: %d\n", __FILE__, __LINE__); fflush(stdout); } // Delete all traces #define UNTRACE BC_Signals::delete_traces(); #else #define TRACE(text) ; #define UNTRACE ; #define PRINT_TRACE { printf("%s: %d\n", __FILE__, __LINE__); fflush(stdout); } //#define PRINT_TRACE ; #define SET_TRACE ; #endif #ifdef TRACE_LOCKS // Before user acquires #define SET_LOCK(ptr, title, location) int table_id = BC_Signals::set_lock(ptr, title, location); // After successful acquisition of a mutex, the table is flagged #define SET_LOCK2 BC_Signals::set_lock2(table_id); // After successful acquisition of a condition, the table is removed because // the user never unlocks a condition after locking it. // Release current lock table after failing to acquire #define UNSET_LOCK2 BC_Signals::unset_lock2(table_id); // Release current owner of lock #define UNSET_LOCK(ptr) BC_Signals::unset_lock(ptr); // Delete a lock #define UNSET_ALL_LOCKS(ptr) BC_Signals::unset_all_locks(ptr); #define LOCK_LOCKS(s) BC_Signals::lock_locks(s); #define UNLOCK_LOCKS BC_Signals::unlock_locks(); #define CLEAR_LOCKS_TID(tid) BC_Signals::clear_locks_tid(tid); #else #define SET_LOCK(ptr, title, location) ; #define SET_LOCK2 ; #define SET_LOCK2_CONDITION ; #define UNSET_LOCK(ptr) ; #define UNSET_LOCK2 ; #define UNSET_ALL_LOCKS(ptr) ; #define LOCK_LOCKS(s) ; #define UNLOCK_LOCKS ; #define CLEAR_LOCKS_TID(tid) ; #endif #ifdef TRACE_MEMORY #define ENABLE_BUFFER BC_Signals::enable_memory(); #define DISABLE_BUFFER BC_Signals::disable_memory(); // Note the size, pointer, and location of an allocation #define BUFFER(size, ptr, location) BC_Signals::set_buffer(size, ptr, location); // Note the pointer and location of an allocation #define BUFFER2(ptr, location) BC_Signals::set_buffer(0, ptr, location); // Remove a pointer from the allocation table #define UNBUFFER(ptr) BC_Signals::unset_buffer(ptr); #else #define ENABLE_BUFFER ; #define DISABLE_BUFFER ; #define BUFFER(size, ptr, location); #define UNBUFFER(ptr); #endif // Handling of temporary files in crash #define SET_TEMP BC_Signals::set_temp #define UNSET_TEMP BC_Signals::unset_temp // Forks need to reset the lock status in case they forked when a lock was held. static void reset_locks(); // Temporary files static void delete_temps(); static void set_temp(char *string); static void unset_temp(char *string); static void signal_dump(int signum); static void kill_subs(); static int set_lock(void *ptr, const char *title, const char *location); static void set_lock2(int table_id); static void set_lock2_condition(int table_id); static void unset_lock2(int table_id); static void unset_lock(void *ptr); // Used in lock destructors so takes away all references static void unset_all_locks(void *ptr); static void clear_locks_tid(pthread_t tid); static void new_trace(const char *text); static void new_trace(const char *file, const char *function, int line); static void delete_traces(); static void enable_memory(); static void disable_memory(); static void set_buffer(int size, void *ptr, const char* location); // This one returns 1 if the buffer wasn't found. static int unset_buffer(void *ptr); static void lock_locks(const char *s); static void unlock_locks(); static void dump_traces(FILE *fp=stdout); static void dump_locks(FILE *fp=stdout); static void dump_buffers(FILE *fp=stdout); static void set_sighup_exit(int enable); static void set_trap_path(const char *path); static void set_trap_hook(void (*hook)(FILE *fp, void *data), void *data); static void set_catch_segv(bool v); static void set_catch_intr(bool v); // Convert signum to text static const char* sig_to_str(int number); static BC_Signals *global_signals; static const char *trap_path; static void *trap_data; static void (*trap_hook)(FILE *fp, void *vp); static bool trap_sigsegv, trap_sigintr; }; #endif