VG_(startup)();
}
+__attribute__((noreturn))
void vgPlain_unimp ( char* what )
{
char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
/*-------------------*/
+/* 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 )
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");
}
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
VG_(startup)();
}
+__attribute__((noreturn))
void vgPlain_unimp ( char* what )
{
char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
/*-------------------*/
+/* 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 )
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");
}
}
+/* 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
-------------------------------------------------------- */
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
VG_(startup)();
}
+__attribute__((noreturn))
void vgPlain_unimp ( char* what )
{
char* ig = "valgrind's libpthread.so: UNIMPLEMENTED FUNCTION: ";
/*-------------------*/
+/* 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 )
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");
}
}
+/* 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
-------------------------------------------------------- */
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)) {
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 */