I need to walk the stack from within an asynchronous signal handler, and every once in a while, the program crashes in uw_frame_state_for. I know that unwinding through a signal handler is 'discouraged', and that proper unwinding information may not always be there, but the unwinder should fail gracefully if that is indeed the case and not crash the program.
See the test program below for reproducing this bug. Dynamic memory allocation may be involved as the new/delete seems to be required to trigger the issue (at least in the test program). On x86-64, this problem affects at least gcc-4.0.3, gcc-4.1.1, gcc-4.2.1, gcc-4.2.4-1ubuntu3, and gcc-4.3.2 I have not been able to reproduce it on i486, ia64, or sparc-solaris. ---- Config: Using built-in specs. Target: x86_64-unknown-linux-gnu Configured with: ../src/configure --prefix=/u/usystem/software/gcc/gcc-4.3.2 --enable-languages=c,c++ --with-gmp=/u/usystem/software/gcc/gmp-4.2.4 --with-mpfr=/u/usystem/software/gcc/mpfr-2.3.2 Thread model: posix gcc version 4.3.2 (GCC) libc6: 2.7-10ubuntu4 Kernel: Linux 2.6.24-23-generic #1 SMP Wed Apr 1 21:43:24 UTC 2009 x86_64 GNU/Linux ------ %%%%%% ------ /* sigunwind.cc compile: g++ sigunwind.cc run: ./a.out */ #include <signal.h> #include <sys/time.h> #include <unwind.h> #include <ucontext.h> #include <stdlib.h> #define __U_SIGCXT__ ucontext_t * #define __U_SIGPARMS__ int sig, siginfo_t *sfp, __U_SIGCXT__ cxt int main(); typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) (struct _Unwind_Context *, void *); extern "C" _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); static _Unwind_Reason_Code extfn ( _Unwind_Context *context, void * arg ) { int i; void * rs = (void *)_Unwind_GetRegionStart(context); if ( rs == main ) { // if we go all the way through to main return _URC_HANDLER_FOUND; // just stop unwinding } // if return _URC_NO_REASON; } void backtrace() { _Unwind_Reason_Code ret = _Unwind_Backtrace( extfn, NULL ); } void rec( int i ) { if ( i <= 0 ) return; int *b = new int; rec( i - 1 ); delete b; } void doit( __U_SIGPARMS__ ) { backtrace(); } int main() { itimerval it; struct sigaction act; //set up signal handler act.sa_sigaction = (void (*)(int, siginfo_t*, void*))doit; sigemptyset( &act.sa_mask ); sigaddset( &act.sa_mask, SIGALRM ); // disable during signal handler sigaddset( &act.sa_mask, SIGVTALRM ); act.sa_flags = SA_SIGINFO; if ( sigaction( SIGALRM, &act, NULL ) == -1 ) exit( -1 ); //set up alarm it.it_interval.tv_sec = 0; it.it_interval.tv_usec = 50000; it.it_value.tv_sec = 0; it.it_value.tv_usec = 50000; setitimer( ITIMER_REAL, &it, NULL ); for ( ; ; ) { rec(10); // run until crash } } -- Summary: uw_frame_state_for can segfault when called by _Unwind_Backtrace from asynchronous signal handler Product: gcc Version: 4.3.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rkrische at uwaterloo dot ca GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40466