]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
The two patches attached resolve the exit-hang (of OOo) bug for me. The first
authorNicholas Nethercote <njn@valgrind.org>
Sat, 26 Mar 2005 20:08:06 +0000 (20:08 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Sat, 26 Mar 2005 20:08:06 +0000 (20:08 +0000)
fixes getppid(), and the second fixes the next bug which is revealed
once getppid() does what LinuxThreads wants;  LinuxThreads uses SIGKILL
to kill off stray threads, but if we send naked SIGKILLs to Valgrind
threads, they'll die without cleaning up or informing anyone of their
death, which means that they're waited on forever.

ADAPTED FROM CVS HEAD

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3449

coregrind/core.h
coregrind/linux/core_os.h
coregrind/linux/syscalls.c
coregrind/vg_syscalls.c
coregrind/x86-linux/syscalls.c

index 3b47f0fd85abbd33b06aff690652b75ab5759b7f..8108a12dbac18b96b8c223bf211149c6659257cd 100644 (file)
@@ -1134,6 +1134,10 @@ Bool VG_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
 Bool VG_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool soft);
 
 void VG_(record_fd_open)(ThreadId tid, Int fd, char *pathname);
+
+// Used when killing threads -- we must not kill a thread if it's the thread
+// that would do Valgrind's final cleanup and output.
+Bool VG_(do_sigkill)(Int pid, Int tgid);
    
 // Flags describing syscall wrappers
 #define Special    (1 << 0)    /* handled specially                    */
@@ -1413,8 +1417,6 @@ GEN_SYSCALL_WRAPPER(sys_mq_timedsend);          // * P?
 GEN_SYSCALL_WRAPPER(sys_mq_timedreceive);       // * P?
 GEN_SYSCALL_WRAPPER(sys_mq_notify);             // * P?
 GEN_SYSCALL_WRAPPER(sys_mq_getsetattr);         // * P?
-GEN_SYSCALL_WRAPPER(sys_tkill);                        // * L
-GEN_SYSCALL_WRAPPER(sys_tgkill);               // * L
 GEN_SYSCALL_WRAPPER(sys_gettid);               // * L?
 
 #undef GEN_SYSCALL_WRAPPER
index ce44d4486f10b9d218d43b19412255b44b0381d3..da159a2fa045976bb3936bbf217fcebbb9558c22 100644 (file)
@@ -82,6 +82,7 @@ VGO_LINUX_SYSCALL_WRAPPER(sys_epoll_create);
 VGO_LINUX_SYSCALL_WRAPPER(sys_epoll_ctl);
 VGO_LINUX_SYSCALL_WRAPPER(sys_epoll_wait);
 
+VGO_LINUX_SYSCALL_WRAPPER(sys_tkill);
 VGO_LINUX_SYSCALL_WRAPPER(sys_tgkill);
 
 VGO_LINUX_SYSCALL_WRAPPER(sys_io_setup);
index 3d0d9ce9e6c622a2ba9109918ea4d2ba1ac0725a..4f340b8453117b9f69bf15b94148414511033847 100644 (file)
@@ -503,13 +503,52 @@ POST(sys_epoll_wait)
       POST_MEM_WRITE( ARG2, sizeof(struct epoll_event)*RES ) ;
 }
 
-PRE(sys_tgkill, 0)
+PRE(sys_tkill, Special)
+{
+   /* int tkill(pid_t tid, int sig); */
+   PRINT("sys_tkill ( %d, %d )", ARG1,ARG2);
+   PRE_REG_READ2(long, "tkill", int, tid, int, sig);
+   if (!VG_(client_signal_OK)(ARG2)) {
+      SET_RESULT( -VKI_EINVAL );
+      return;
+   }
+
+   /* If we're sending SIGKILL, check to see if the target is one of
+      our threads and handle it specially. */
+   if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1))
+      SET_RESULT(0);
+   else
+      SET_RESULT(VG_(do_syscall2)(SYSNO, ARG1, ARG2));
+
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d",
+                  ARG2, ARG1);
+   // Check to see if this kill gave us a pending signal
+   VG_(poll_signals)(tid);
+}
+
+PRE(sys_tgkill, Special)
 {
    /* int tgkill(pid_t tgid, pid_t tid, int sig); */
    PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3);
    PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig);
-   if (!VG_(client_signal_OK)(ARG3))
+   if (!VG_(client_signal_OK)(ARG3)) {
       SET_RESULT( -VKI_EINVAL );
+      return;
+   }
+   
+   /* If we're sending SIGKILL, check to see if the target is one of
+      our threads and handle it specially. */
+   if (ARG3 == VKI_SIGKILL && VG_(do_sigkill)(ARG2, ARG1))
+      SET_RESULT(0);
+   else
+      SET_RESULT(VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3));
+
+   if (VG_(clo_trace_signals))
+      VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d",
+                  ARG3, ARG1, ARG2);
+   // Check to see if this kill gave us a pending signal
+   VG_(poll_signals)(tid);
 }
 
 POST(sys_tgkill)
index 46c2d90d3a271f73c9a4a9e3445f30e616447377..45d3eb60eaf2a74754eb4faa2785a29af046fcb7 100644 (file)
@@ -2946,6 +2946,16 @@ PRE(sys_getppid, 0)
    PRE_REG_READ0(long, "getppid");
 }
 
+POST(sys_getppid)
+{
+   /* If the master thread has already exited, and it is this thread's
+      parent, then force getppid to return 1 (init) rather than the
+      real ppid, so that it thinks its parent has exited. */
+   if (VG_(threads)[VG_(master_tid)].os_state.lwpid == RES &&
+       VG_(is_exiting)(VG_(master_tid)))
+      RES = 1;
+}
+
 static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
 {
    POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
@@ -4319,20 +4329,76 @@ POST(sys_ioctl)
    }
 }
 
-PRE(sys_kill, 0)
+/* 
+   If we're sending a SIGKILL to one of our own threads, then simulate
+   it rather than really sending the signal, so that the target thread
+   gets a chance to clean up.  Returns True if we did the killing (or
+   no killing is necessary), and False if the caller should use the
+   normal kill syscall.
+   
+   "pid" is any pid argument which can be passed to kill; group kills
+   (< -1, 0), and owner kills (-1) are ignored, on the grounds that
+   they'll most likely hit all the threads and we won't need to worry
+   about cleanup.  In truth, we can't fully emulate these multicast
+   kills.
+
+   "tgid" is a thread group id.  If it is not -1, then the target
+   thread must be in that thread group.
+ */
+Bool VG_(do_sigkill)(Int pid, Int tgid)
+{
+   ThreadState *tst;
+   ThreadId tid;
+
+   if (pid <= 0)
+      return False;
+
+   tid = VG_(get_lwp_tid)(pid);
+   if (tid == VG_INVALID_THREADID)
+      return False;            /* none of our threads */
+
+   tst = VG_(get_ThreadState)(tid);
+   if (tst == NULL || tst->status == VgTs_Empty)
+      return False;            /* hm, shouldn't happen */
+
+   if (tgid != -1 && tst->os_state.threadgroup != tgid)
+      return False;            /* not the right thread group */
+
+   /* Check to see that the target isn't already exiting. */
+   if (!VG_(is_exiting)(tid)) {
+      if (VG_(clo_trace_signals))
+        VG_(message)(Vg_DebugMsg, "Thread %d being killed with SIGKILL", tst->tid);
+      
+      tst->exitreason = VgSrc_FatalSig;
+      tst->os_state.fatalsig = VKI_SIGKILL;
+      
+      if (!VG_(is_running_thread)(tid))
+        VG_(kill_thread)(tid);
+   }
+   
+   return True;
+}
+
+PRE(sys_kill, Special)
 {
    /* int kill(pid_t pid, int sig); */
    PRINT("sys_kill ( %d, %d )", ARG1,ARG2);
    PRE_REG_READ2(long, "kill", int, pid, int, sig);
-   if (!VG_(client_signal_OK)(ARG2))
+   if (!VG_(client_signal_OK)(ARG2)) {
       SET_RESULT( -VKI_EINVAL );
-}
+      return;
+   }
+
+   /* If we're sending SIGKILL, check to see if the target is one of
+      our threads and handle it specially. */
+   if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1))
+      SET_RESULT(0);
+   else
+      SET_RESULT(VG_(do_syscall2)(SYSNO, ARG1, ARG2));
 
-POST(sys_kill)
-{
    if (VG_(clo_trace_signals))
       VG_(message)(Vg_DebugMsg, "kill: sent signal %d to pid %d",
-                   ARG2, ARG1);
+                  ARG2, ARG1);
    // Check to see if this kill gave us a pending signal
    VG_(poll_signals)(tid);
 }
index b4f7fc8182105d48b5de48c037a3cd577bc10ece..ce4f72846cc7a30f75eee66a79f66164bcce8d36 100644 (file)
@@ -1017,7 +1017,7 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
 
    GENX_(__NR_ftime,             sys_ni_syscall),     // 35
    GENX_(__NR_sync,              sys_sync),           // 36
-   GENXY(__NR_kill,              sys_kill),           // 37
+   GENX_(__NR_kill,              sys_kill),           // 37
    GENX_(__NR_rename,            sys_rename),         // 38
    GENX_(__NR_mkdir,             sys_mkdir),          // 39
 
@@ -1049,7 +1049,7 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    GENX_(__NR_chroot,            sys_chroot),         // 61
    //   (__NR_ustat,             sys_ustat)           // 62 SVr4 -- deprecated
    GENXY(__NR_dup2,              sys_dup2),           // 63
-   GENX_(__NR_getppid,           sys_getppid),        // 64
+   GENXY(__NR_getppid,           sys_getppid),        // 64
 
    GENX_(__NR_getpgrp,           sys_getpgrp),        // 65
    GENX_(__NR_setsid,            sys_setsid),         // 66
@@ -1261,7 +1261,7 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    GENX_(__NR_removexattr,       sys_removexattr),    // 235
    GENX_(__NR_lremovexattr,      sys_lremovexattr),   // 236
    GENX_(__NR_fremovexattr,      sys_fremovexattr),   // 237
-   //   (__NR_tkill,             sys_tkill),          // 238 */Linux
+   LINX_(__NR_tkill,             sys_tkill),          // 238 */Linux
    LINXY(__NR_sendfile64,        sys_sendfile64),     // 239
 
    LINXY(__NR_futex,             sys_futex),             // 240
@@ -1300,7 +1300,7 @@ const struct SyscallTableEntry VGA_(syscall_table)[] = {
    GENXY(__NR_statfs64,          sys_statfs64),       // 268
    GENXY(__NR_fstatfs64,         sys_fstatfs64),      // 269
 
-   LINXY(__NR_tgkill,            sys_tgkill),         // 270 */Linux
+   LINX_(__NR_tgkill,            sys_tgkill),         // 270 */Linux
    GENX_(__NR_utimes,            sys_utimes),         // 271
    //   (__NR_fadvise64_64,      sys_fadvise64_64),   // 272 */(Linux?)
    GENX_(__NR_vserver,           sys_ni_syscall),     // 273