From: Julian Seward Date: Sat, 13 Jul 2002 12:12:56 +0000 (+0000) Subject: vg_signals.c: vg_oursignalhandler(): don't longjmp() on fatal signal if X-Git-Tag: svn/VALGRIND_1_0_3~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27c607b91feec7e850646f431e49b57e048cc9a7;p=thirdparty%2Fvalgrind.git vg_signals.c: vg_oursignalhandler(): don't longjmp() on fatal signal if the scheduler's jmp_buf is not valid. This might avoid at least some of the following: vg_scheduler.c:479 (run_thread_for_a_while): Assertion `trc == 0' failed. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@490 --- diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index d489be3ebc..40506c126b 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -776,6 +776,10 @@ extern void VG_(pp_sched_status) ( void ); /* vg_oursignalhandler() might longjmp(). Here's the jmp_buf. */ extern jmp_buf VG_(scheduler_jmpbuf); +/* This says whether scheduler_jmpbuf is actually valid. Needed so + that our signal handler doesn't longjmp when the buffer isn't + actually valid. */ +extern Bool VG_(scheduler_jmpbuf_valid); /* ... and if so, here's the signal which caused it to do so. */ extern Int VG_(longjmpd_on_signal); diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index 6a99730beb..12024e0599 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -99,6 +99,10 @@ static Int vg_tid_currently_in_baseBlock = VG_INVALID_THREADID; /* vg_oursignalhandler() might longjmp(). Here's the jmp_buf. */ jmp_buf VG_(scheduler_jmpbuf); +/* This says whether scheduler_jmpbuf is actually valid. Needed so + that our signal handler doesn't longjmp when the buffer isn't + actually valid. */ +Bool VG_(scheduler_jmpbuf_valid) = False; /* ... and if so, here's the signal which caused it to do so. */ Int VG_(longjmpd_on_signal); @@ -466,19 +470,26 @@ UInt run_thread_for_a_while ( ThreadId tid ) vg_assert(VG_(is_valid_tid)(tid)); vg_assert(VG_(threads)[tid].status == VgTs_Runnable); vg_assert(VG_(bbs_to_go) > 0); + vg_assert(!VG_(scheduler_jmpbuf_valid)); VGP_PUSHCC(VgpRun); VG_(load_thread_state) ( tid ); if (__builtin_setjmp(VG_(scheduler_jmpbuf)) == 0) { /* try this ... */ + VG_(scheduler_jmpbuf_valid) = True; trc = VG_(run_innerloop)(); + VG_(scheduler_jmpbuf_valid) = False; /* We get here if the client didn't take a fault. */ } else { /* We get here if the client took a fault, which caused our signal handler to longjmp. */ + VG_(scheduler_jmpbuf_valid) = False; vg_assert(trc == 0); trc = VG_TRC_UNRESUMABLE_SIGNAL; } + + vg_assert(!VG_(scheduler_jmpbuf_valid)); + VG_(save_thread_state) ( tid ); VGP_POPCC; return trc; @@ -596,6 +607,9 @@ void VG_(scheduler_init) ( void ) /* So now ... */ vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID); + + /* Not running client code right now. */ + VG_(scheduler_jmpbuf_valid) = False; } diff --git a/coregrind/vg_signals.c b/coregrind/vg_signals.c index 3dce4d8dec..f58ec11e96 100644 --- a/coregrind/vg_signals.c +++ b/coregrind/vg_signals.c @@ -1258,6 +1258,7 @@ Bool VG_(deliver_signals) ( void ) static void vg_oursignalhandler ( Int sigNo ) { + static UInt segv_warns = 0; ThreadId tid; Int dummy_local; Bool sane; @@ -1352,13 +1353,26 @@ void vg_oursignalhandler ( Int sigNo ) signals. */ VG_(restore_all_host_signals)( &saved_procmask ); - if (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS - || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL) { + if ( (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS + || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL) + && + VG_(scheduler_jmpbuf_valid) + ) { /* Can't continue; must longjmp back to the scheduler and thus enter the sighandler immediately. */ VG_(longjmpd_on_signal) = sigNo; __builtin_longjmp(VG_(scheduler_jmpbuf),1); } + + if (sigNo == VKI_SIGSEGV && !VG_(scheduler_jmpbuf_valid)) { + if (++segv_warns <= 3) { + VG_(message)(Vg_UserMsg, + "Warning: SIGSEGV not in user code; either from syscall kill()" ); + VG_(message)(Vg_UserMsg, + " or possible Valgrind bug. " + "This message is only shown 3 times." ); + } + } } diff --git a/vg_include.h b/vg_include.h index d489be3ebc..40506c126b 100644 --- a/vg_include.h +++ b/vg_include.h @@ -776,6 +776,10 @@ extern void VG_(pp_sched_status) ( void ); /* vg_oursignalhandler() might longjmp(). Here's the jmp_buf. */ extern jmp_buf VG_(scheduler_jmpbuf); +/* This says whether scheduler_jmpbuf is actually valid. Needed so + that our signal handler doesn't longjmp when the buffer isn't + actually valid. */ +extern Bool VG_(scheduler_jmpbuf_valid); /* ... and if so, here's the signal which caused it to do so. */ extern Int VG_(longjmpd_on_signal); diff --git a/vg_scheduler.c b/vg_scheduler.c index 6a99730beb..12024e0599 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -99,6 +99,10 @@ static Int vg_tid_currently_in_baseBlock = VG_INVALID_THREADID; /* vg_oursignalhandler() might longjmp(). Here's the jmp_buf. */ jmp_buf VG_(scheduler_jmpbuf); +/* This says whether scheduler_jmpbuf is actually valid. Needed so + that our signal handler doesn't longjmp when the buffer isn't + actually valid. */ +Bool VG_(scheduler_jmpbuf_valid) = False; /* ... and if so, here's the signal which caused it to do so. */ Int VG_(longjmpd_on_signal); @@ -466,19 +470,26 @@ UInt run_thread_for_a_while ( ThreadId tid ) vg_assert(VG_(is_valid_tid)(tid)); vg_assert(VG_(threads)[tid].status == VgTs_Runnable); vg_assert(VG_(bbs_to_go) > 0); + vg_assert(!VG_(scheduler_jmpbuf_valid)); VGP_PUSHCC(VgpRun); VG_(load_thread_state) ( tid ); if (__builtin_setjmp(VG_(scheduler_jmpbuf)) == 0) { /* try this ... */ + VG_(scheduler_jmpbuf_valid) = True; trc = VG_(run_innerloop)(); + VG_(scheduler_jmpbuf_valid) = False; /* We get here if the client didn't take a fault. */ } else { /* We get here if the client took a fault, which caused our signal handler to longjmp. */ + VG_(scheduler_jmpbuf_valid) = False; vg_assert(trc == 0); trc = VG_TRC_UNRESUMABLE_SIGNAL; } + + vg_assert(!VG_(scheduler_jmpbuf_valid)); + VG_(save_thread_state) ( tid ); VGP_POPCC; return trc; @@ -596,6 +607,9 @@ void VG_(scheduler_init) ( void ) /* So now ... */ vg_assert(vg_tid_currently_in_baseBlock == VG_INVALID_THREADID); + + /* Not running client code right now. */ + VG_(scheduler_jmpbuf_valid) = False; } diff --git a/vg_signals.c b/vg_signals.c index 3dce4d8dec..f58ec11e96 100644 --- a/vg_signals.c +++ b/vg_signals.c @@ -1258,6 +1258,7 @@ Bool VG_(deliver_signals) ( void ) static void vg_oursignalhandler ( Int sigNo ) { + static UInt segv_warns = 0; ThreadId tid; Int dummy_local; Bool sane; @@ -1352,13 +1353,26 @@ void vg_oursignalhandler ( Int sigNo ) signals. */ VG_(restore_all_host_signals)( &saved_procmask ); - if (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS - || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL) { + if ( (sigNo == VKI_SIGSEGV || sigNo == VKI_SIGBUS + || sigNo == VKI_SIGFPE || sigNo == VKI_SIGILL) + && + VG_(scheduler_jmpbuf_valid) + ) { /* Can't continue; must longjmp back to the scheduler and thus enter the sighandler immediately. */ VG_(longjmpd_on_signal) = sigNo; __builtin_longjmp(VG_(scheduler_jmpbuf),1); } + + if (sigNo == VKI_SIGSEGV && !VG_(scheduler_jmpbuf_valid)) { + if (++segv_warns <= 3) { + VG_(message)(Vg_UserMsg, + "Warning: SIGSEGV not in user code; either from syscall kill()" ); + VG_(message)(Vg_UserMsg, + " or possible Valgrind bug. " + "This message is only shown 3 times." ); + } + } }