|
From: Julian S. <js...@ac...> - 2005-03-21 20:26:41
|
CVS commit by jseward:
A second patch from Jeremy, which is also required to solve the
OOo-on-LinuxThreads hangs at exit problem. This patch goes along
with (vg_syscalls.c 1.262, x86-linux/syscalls.c 1.28).
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.
M +83 -15 vg_syscalls.c 1.263
M +3 -3 x86-linux/syscalls.c 1.29
--- valgrind/coregrind/vg_syscalls.c #1.262:1.263
@@ -4205,15 +4205,71 @@ POST(sys_ioctl)
}
-PRE(sys_tkill, 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.
+ */
+static Bool 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_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))
+ 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 && do_sigkill(arg1, -1))
+ set_result(0);
+ else
+ set_result(VG_(do_syscall)(SYSNO, arg1, arg2));
-POST(sys_tkill)
-{
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d",
@@ -4223,15 +4279,21 @@ POST(sys_tkill)
}
-PRE(sys_tgkill, 0)
+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 && do_sigkill(arg2, arg1))
+ set_result(0);
+ else
+ set_result(VG_(do_syscall)(SYSNO, arg1, arg2, arg3));
-POST(sys_tgkill)
-{
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d",
@@ -4241,15 +4303,21 @@ POST(sys_tgkill)
}
-PRE(sys_kill, 0)
+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 && do_sigkill(arg1, -1))
+ set_result(0);
+ else
+ set_result(VG_(do_syscall)(SYSNO, arg1, arg2));
-POST(sys_kill)
-{
if (VG_(clo_trace_signals))
VG_(message)(Vg_DebugMsg, "kill: sent signal %d to pid %d",
--- valgrind/coregrind/x86-linux/syscalls.c #1.28:1.29
@@ -743,5 +743,5 @@ const struct SyscallTableEntry VGA_(sysc
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
@@ -987,5 +987,5 @@ const struct SyscallTableEntry VGA_(sysc
GENX_(__NR_lremovexattr, sys_lremovexattr), // 236
GENX_(__NR_fremovexattr, sys_fremovexattr), // 237
- GENXY(__NR_tkill, sys_tkill), // 238 Linux
+ GENX_(__NR_tkill, sys_tkill), // 238 Linux
LINXY(__NR_sendfile64, sys_sendfile64), // 239
@@ -1026,5 +1026,5 @@ const struct SyscallTableEntry VGA_(sysc
GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
- GENXY(__NR_tgkill, sys_tgkill), // 270
+ GENX_(__NR_tgkill, sys_tgkill), // 270
GENX_(__NR_utimes, sys_utimes), // 271
// (__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
|