From: Julian Seward Date: Wed, 29 May 2002 19:26:32 +0000 (+0000) Subject: As per POSIX, nuke all threads other than me X-Git-Tag: svn/VALGRIND_1_0_3~133 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0943acb8fdefd714258122d37fe646e8d94c2a63;p=thirdparty%2Fvalgrind.git As per POSIX, nuke all threads other than me - just before __NR_exec() - just after __NR_fork() when I am the child This makes OpenOffice 1.0 not have mutex-related assertion failures git-svn-id: svn://svn.valgrind.org/valgrind/trunk@333 --- diff --git a/coregrind/arch/x86-linux/vg_libpthread.c b/coregrind/arch/x86-linux/vg_libpthread.c index 7c6815f59e..8d5ef2f368 100644 --- a/coregrind/arch/x86-linux/vg_libpthread.c +++ b/coregrind/arch/x86-linux/vg_libpthread.c @@ -171,6 +171,7 @@ static void not_inside ( char* msg ) VG_(startup)(); } +__attribute__((noreturn)) void vgPlain_unimp ( char* what ) { char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: "; @@ -896,6 +897,9 @@ void pthread_testcancel ( void ) /*-------------------*/ +/* If this is indeed used by LinuxThreads to implement thread nuking + post fork and pre exec, we should really nuke em, not do + pthread_cancel. */ static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; void __pthread_kill_other_threads_np ( void ) @@ -1079,10 +1083,9 @@ int __pthread_atfork ( void (*prepare)(void), void (*parent)(void), void (*child)(void) ) { - static int moans = N_MOANS; - if (moans-- > 0) - ignored("pthread_atfork"); - return 0; + /* We have to do this properly or not at all; faking it isn't an + option. */ + vgPlain_unimp("__pthread_atfork"); } diff --git a/coregrind/vg_include.h b/coregrind/vg_include.h index 290fbec739..840282b200 100644 --- a/coregrind/vg_include.h +++ b/coregrind/vg_include.h @@ -691,6 +691,9 @@ extern ThreadId VG_(get_current_tid) ( void ); error message generation. */ extern ThreadId VG_(identify_stack_addr)( Addr a ); +/* Nuke all threads except tid. */ +extern void VG_(nuke_all_threads_except) ( ThreadId me ); + /* Return codes from the scheduler. */ typedef diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c index 7c6815f59e..8d5ef2f368 100644 --- a/coregrind/vg_libpthread.c +++ b/coregrind/vg_libpthread.c @@ -171,6 +171,7 @@ static void not_inside ( char* msg ) VG_(startup)(); } +__attribute__((noreturn)) void vgPlain_unimp ( char* what ) { char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: "; @@ -896,6 +897,9 @@ void pthread_testcancel ( void ) /*-------------------*/ +/* If this is indeed used by LinuxThreads to implement thread nuking + post fork and pre exec, we should really nuke em, not do + pthread_cancel. */ static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; void __pthread_kill_other_threads_np ( void ) @@ -1079,10 +1083,9 @@ int __pthread_atfork ( void (*prepare)(void), void (*parent)(void), void (*child)(void) ) { - static int moans = N_MOANS; - if (moans-- > 0) - ignored("pthread_atfork"); - return 0; + /* We have to do this properly or not at all; faking it isn't an + option. */ + vgPlain_unimp("__pthread_atfork"); } diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c index c631456481..0e2ce294b6 100644 --- a/coregrind/vg_scheduler.c +++ b/coregrind/vg_scheduler.c @@ -1686,6 +1686,24 @@ void maybe_rendezvous_joiners_and_joinees ( void ) } +/* Nuke all threads other than tid. POSIX specifies that this should + happen in __NR_exec, and after a __NR_fork() when I am the child, + as POSIX requires. */ +void VG_(nuke_all_threads_except) ( ThreadId me ) +{ + ThreadId tid; + for (tid = 1; tid < VG_N_THREADS; tid++) { + if (tid == me + || VG_(threads)[tid].status == VgTs_Empty) + continue; + VG_(printf)( + "VG_(nuke_all_threads_except): nuking tid %d\n", tid); + VG_(threads)[tid].status = VgTs_Empty; + cleanup_after_thread_exited( tid ); + } +} + + /* ----------------------------------------------------------- Thread CREATION, JOINAGE and CANCELLATION: REQUESTS -------------------------------------------------------- */ diff --git a/vg_include.h b/vg_include.h index 290fbec739..840282b200 100644 --- a/vg_include.h +++ b/vg_include.h @@ -691,6 +691,9 @@ extern ThreadId VG_(get_current_tid) ( void ); error message generation. */ extern ThreadId VG_(identify_stack_addr)( Addr a ); +/* Nuke all threads except tid. */ +extern void VG_(nuke_all_threads_except) ( ThreadId me ); + /* Return codes from the scheduler. */ typedef diff --git a/vg_libpthread.c b/vg_libpthread.c index 7c6815f59e..8d5ef2f368 100644 --- a/vg_libpthread.c +++ b/vg_libpthread.c @@ -171,6 +171,7 @@ static void not_inside ( char* msg ) VG_(startup)(); } +__attribute__((noreturn)) void vgPlain_unimp ( char* what ) { char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: "; @@ -896,6 +897,9 @@ void pthread_testcancel ( void ) /*-------------------*/ +/* If this is indeed used by LinuxThreads to implement thread nuking + post fork and pre exec, we should really nuke em, not do + pthread_cancel. */ static pthread_mutex_t massacre_mx = PTHREAD_MUTEX_INITIALIZER; void __pthread_kill_other_threads_np ( void ) @@ -1079,10 +1083,9 @@ int __pthread_atfork ( void (*prepare)(void), void (*parent)(void), void (*child)(void) ) { - static int moans = N_MOANS; - if (moans-- > 0) - ignored("pthread_atfork"); - return 0; + /* We have to do this properly or not at all; faking it isn't an + option. */ + vgPlain_unimp("__pthread_atfork"); } diff --git a/vg_scheduler.c b/vg_scheduler.c index c631456481..0e2ce294b6 100644 --- a/vg_scheduler.c +++ b/vg_scheduler.c @@ -1686,6 +1686,24 @@ void maybe_rendezvous_joiners_and_joinees ( void ) } +/* Nuke all threads other than tid. POSIX specifies that this should + happen in __NR_exec, and after a __NR_fork() when I am the child, + as POSIX requires. */ +void VG_(nuke_all_threads_except) ( ThreadId me ) +{ + ThreadId tid; + for (tid = 1; tid < VG_N_THREADS; tid++) { + if (tid == me + || VG_(threads)[tid].status == VgTs_Empty) + continue; + VG_(printf)( + "VG_(nuke_all_threads_except): nuking tid %d\n", tid); + VG_(threads)[tid].status = VgTs_Empty; + cleanup_after_thread_exited( tid ); + } +} + + /* ----------------------------------------------------------- Thread CREATION, JOINAGE and CANCELLATION: REQUESTS -------------------------------------------------------- */ diff --git a/vg_syscall_mem.c b/vg_syscall_mem.c index 0c5d88861e..518c54aae2 100644 --- a/vg_syscall_mem.c +++ b/vg_syscall_mem.c @@ -895,6 +895,9 @@ void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid ) if (VG_(clo_trace_syscalls)) VG_(printf)("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n", arg1, arg1, arg2, arg3); + /* Resistance is futile. Nuke all other threads. POSIX + mandates this. */ + VG_(nuke_all_threads_except)( tid ); /* Make any binding for LD_PRELOAD disappear, so that child processes don't get traced into. */ if (!VG_(clo_trace_children)) { @@ -1103,6 +1106,11 @@ void VG_(perform_assumed_nonblocking_syscall) ( ThreadId tid ) if (VG_(clo_trace_syscalls)) VG_(printf)("fork ()\n"); KERNEL_DO_SYSCALL(tid,res); + if (res == 0) { + /* I am the child. Nuke all other threads which I might + have inherited from my parent. POSIX mandates this. */ + VG_(nuke_all_threads_except)( tid ); + } break; case __NR_fsync: /* syscall 118 */