From: Nicholas Nethercote Date: Tue, 28 Apr 2009 01:55:01 +0000 (+0000) Subject: Merged r9653..r9655 (fixed terminal signal handling in Darwin) from DARWIN X-Git-Tag: svn/VALGRIND_3_5_0~760 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c601f8a1e41a1ee3465c6d8057fc54dd7fe842e7;p=thirdparty%2Fvalgrind.git Merged r9653..r9655 (fixed terminal signal handling in Darwin) from DARWIN branch. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9656 --- diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c index e5fe845753..31dc5e444d 100644 --- a/coregrind/m_signals.c +++ b/coregrind/m_signals.c @@ -1137,6 +1137,24 @@ void VG_(kill_self)(Int sigNo) VG_(sigprocmask)(VKI_SIG_SETMASK, &origmask, NULL); } +// The si_code describes where the signal came from. Some come from the +// kernel, eg.: seg faults, illegal opcodes. Some come from the user, eg.: +// from kill() (SI_USER), or timer_settime() (SI_TIMER), or an async I/O +// request (SI_ASYNCIO). There's lots of implementation-defined leeway in +// POSIX, but the user vs. kernal distinction is what we want here. +static Bool is_signal_from_kernel(int si_code) +{ +#if defined(VGO_linux) || defined(VGO_aix5) + // On Linux, SI_USER is zero, negative values are from the user, positive + // values are from the kernel. There are SI_FROMUSER and SI_FROMKERNEL + // macros but we don't use them here because other platforms don't have + // them. + return ( si_code > VKI_SI_USER ? True : False ); +#else +# error Unknown OS +#endif +} + /* Perform the default action of a signal. If the signal is fatal, it marks all threads as needing to exit, but it doesn't actually kill @@ -1208,15 +1226,17 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) core = False; } - if ( (VG_(clo_verbosity) > 1 || (could_core && info->si_code > VKI_SI_USER)) - && !VG_(clo_xml) ) { + if ( (VG_(clo_verbosity) > 1 || + (could_core && is_signal_from_kernel(info->si_code)) + ) && + !VG_(clo_xml) ) { VG_(message)(Vg_UserMsg, ""); VG_(message)(Vg_UserMsg, "Process terminating with default action of signal %d (%s)%s", sigNo, signame(sigNo), core ? ": dumping core" : ""); /* Be helpful - decode some more details about this fault */ - if (info->si_code > VKI_SI_USER) { + if (is_signal_from_kernel(info->si_code)) { const Char *event = NULL; Bool haveaddr = True; @@ -1299,7 +1319,7 @@ static void default_action(const vki_siginfo_t *info, ThreadId tid) VG_(pp_ExeContext)( ec ); } if (sigNo == VKI_SIGSEGV - && info && info->si_code > VKI_SI_USER + && info && is_signal_from_kernel(info->si_code) && info->si_code == VKI_SEGV_MAPERR) { VG_(message)(Vg_UserMsg, " If you believe this happened as a " "result of a stack overflow in your"); @@ -1744,7 +1764,24 @@ void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *u info->si_code = (Short)info->si_code; #endif - if (info->si_code <= VKI_SI_USER) { + /* // debug code: + if (0) { + VG_(printf)("info->si_signo %d\n", info->si_signo); + VG_(printf)("info->si_errno %d\n", info->si_errno); + VG_(printf)("info->si_code %d\n", info->si_code); + VG_(printf)("info->si_pid %d\n", info->si_pid); + VG_(printf)("info->si_uid %d\n", info->si_uid); + VG_(printf)("info->si_status %d\n", info->si_status); + VG_(printf)("info->si_addr %p\n", info->si_addr); + } + */ + + /* Figure out if the signal is being sent from outside the process. + (Why do we care?) If the signal is from the user rather than the + kernel,, then treat it more like an async signal than a sync signal -- + that is, merely queue it for later delivery. */ + + if (!is_signal_from_kernel(info->si_code)) { /* If some user-process sent us one of these signals (ie, they're not the result of a faulting instruction), then treat it as an async signal. This is tricky because we could get @@ -1812,7 +1849,7 @@ void sync_signalhandler ( Int sigNo, vki_siginfo_t *info, struct vki_ucontext *u queue_signal(0, info); /* shared pending */ return; - } + } /* if (!is_signal_from_kernel(info->si_code)) */ if (VG_(clo_trace_signals)) { VG_(message)(Vg_DebugMsg, "signal %d arrived ... si_code=%d, " diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am index 2962f8f1ef..72a432ee3c 100644 --- a/memcheck/tests/Makefile.am +++ b/memcheck/tests/Makefile.am @@ -23,9 +23,11 @@ endif DIST_SUBDIRS = x86 amd64 linux x86-linux . -noinst_SCRIPTS = filter_allocs \ - filter_stderr filter_xml \ - filter_varinfo3 +noinst_SCRIPTS = \ + filter_addressable \ + filter_allocs \ + filter_stderr filter_xml \ + filter_varinfo3 EXTRA_DIST = $(noinst_SCRIPTS) \ addressable.stderr.exp addressable.stdout.exp addressable.vgtest \ diff --git a/memcheck/tests/addressable.c b/memcheck/tests/addressable.c index f845ef3d09..bb6da4fce2 100644 --- a/memcheck/tests/addressable.c +++ b/memcheck/tests/addressable.c @@ -93,12 +93,12 @@ static void test5() static struct test { void (*test)(void); - int sig; + int faults; } tests[] = { { test1, 0 }, - { test2, SIGSEGV }, + { test2, 1 }, { test3, 0 }, - { test4, SIGSEGV }, + { test4, 1 }, { test5, 0 }, }; static const int n_tests = sizeof(tests)/sizeof(*tests); @@ -140,18 +140,19 @@ int main() if (WIFSIGNALED(status)) { assert(WTERMSIG(status) != 0); - if (WTERMSIG(status) == tests[i].sig) + if (1 == tests[i].faults && + (WTERMSIG(status) == SIGSEGV || + WTERMSIG(status) == SIGBUS)) printf("PASS\n"); else printf("died with unexpected signal %d\n", WTERMSIG(status)); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == 0) { - if (tests[i].sig == 0) + if (tests[i].faults == 0) printf("PASS\n"); else - printf("exited without expected signal %d\n", - tests[i].sig); + printf("exited without expected SIGSEGV or SIGBUS signal\n"); } else printf("exited with unexpected status %d\n", WEXITSTATUS(status)); diff --git a/memcheck/tests/addressable.stderr.exp b/memcheck/tests/addressable.stderr.exp index ef8265698b..ad76e96c7e 100644 --- a/memcheck/tests/addressable.stderr.exp +++ b/memcheck/tests/addressable.stderr.exp @@ -15,8 +15,8 @@ Invalid write of size 1 by 0x........: main (addressable.c:125) Address 0x........ is not stack'd, malloc'd or (recently) free'd -Process terminating with default action of signal 11 (SIGSEGV) - Access not within mapped region at address 0x........ +Process terminating with default action of signal N (SIGSEGV or SIGBUS) + Bad memory (SIGSEGV or SIGBUS) at address 0x........ at 0x........: test2 (addressable.c:51) by 0x........: main (addressable.c:125) If you believe this happened as a result of a stack overflow in your @@ -36,8 +36,8 @@ malloc/free: ... allocs, ... frees, ... bytes allocated. For a detailed leak analysis, rerun with: --leak-check=yes For counts of detected errors, rerun with: -v -Process terminating with default action of signal 11 (SIGSEGV) - Bad permissions for mapped region at address 0x........ +Process terminating with default action of signal N (SIGSEGV or SIGBUS) + Bad memory (SIGSEGV or SIGBUS) at address 0x........ at 0x........: test4 (addressable.c:74) by 0x........: main (addressable.c:125) diff --git a/memcheck/tests/addressable.stderr.exp2 b/memcheck/tests/addressable.stderr.exp2 deleted file mode 100644 index 4b73958c74..0000000000 --- a/memcheck/tests/addressable.stderr.exp2 +++ /dev/null @@ -1,70 +0,0 @@ - - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v -Unaddressable byte(s) found during client check request - at 0x........: test2 (addressable.c:48) - by 0x........: main (addressable.c:125) - Address 0x........ is not stack'd, malloc'd or (recently) free'd - -Invalid write of size 1 - at 0x........: test2 (addressable.c:51) - by 0x........: main (addressable.c:125) - Address 0x........ is not stack'd, malloc'd or (recently) free'd - -Process terminating with default action of signal 11 (SIGSEGV) - Access not within mapped region at address 0x........ - at 0x........: test2 (addressable.c:51) - by 0x........: main (addressable.c:125) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v - -Process terminating with default action of signal 11 (SIGSEGV) - Bad permissions for mapped region at address 0x........ - at 0x........: test4 (addressable.c:74) - by 0x........: main (addressable.c:125) - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v -Uninitialised byte(s) found during client check request - at 0x........: test5 (addressable.c:85) - by 0x........: main (addressable.c:125) - Address 0x........ is 10 bytes inside a block of size 20480 client-defined - at 0x........: test5 (addressable.c:82) - by 0x........: main (addressable.c:125) - -Uninitialised byte(s) found during client check request - at 0x........: test5 (addressable.c:91) - by 0x........: main (addressable.c:125) - Address 0x........ is 20 bytes inside a block of size 20480 client-defined - at 0x........: test5 (addressable.c:82) - by 0x........: main (addressable.c:125) - -ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v -Use --track-origins=yes to see where uninitialised values come from - -ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) -malloc/free: in use at exit: ... bytes in ... blocks. -malloc/free: ... allocs, ... frees, ... bytes allocated. -For a detailed leak analysis, rerun with: --leak-check=yes -For counts of detected errors, rerun with: -v diff --git a/memcheck/tests/addressable.vgtest b/memcheck/tests/addressable.vgtest index c6c032ba54..c91bff5fa5 100644 --- a/memcheck/tests/addressable.vgtest +++ b/memcheck/tests/addressable.vgtest @@ -1,2 +1,2 @@ prog: addressable -stderr_filter: filter_allocs +stderr_filter: filter_addressable diff --git a/memcheck/tests/filter_addressable b/memcheck/tests/filter_addressable new file mode 100755 index 0000000000..f89cf85be2 --- /dev/null +++ b/memcheck/tests/filter_addressable @@ -0,0 +1,7 @@ +#! /bin/sh + +./filter_allocs | +perl -p -e 's/(default action of signal) [0-9]+ \(SIG(SEGV|BUS)\)/$1 N \(SIGSEGV or SIGBUS\)/' | +perl -p -e 's/(Bad permissions for mapped region|Access not within mapped region|Non-existent physical address) at address 0x/Bad memory (SIGSEGV or SIGBUS) at address 0x/' + +