From da84f473b79b5e5f4359e60ac7424e007ea2b59e Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Thu, 2 Feb 2012 18:06:40 +0000 Subject: [PATCH] 2012-02-02 Pedro Alves Try SIGKILL first, then PTRACE_KILL. * linux-low.c (linux_kill_one_lwp): New. (linux_kill_one_lwp): Rename to ... (kill_one_lwp_callback): ... this. Use the new linux_kill_one_lwp. --- gdb/gdbserver/ChangeLog | 8 +++++++ gdb/gdbserver/linux-low.c | 49 +++++++++++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index cdc8448c7c9..690d2a68c3f 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,11 @@ +2012-02-02 Pedro Alves + + Try SIGKILL first, then PTRACE_KILL. + * linux-low.c (linux_kill_one_lwp): New. + (linux_kill_one_lwp): Rename to ... + (kill_one_lwp_callback): ... this. Use the new + linux_kill_one_lwp. + 2012-02-02 Pedro Alves * tracepoint.c (cmd_qtminftpilen): Return 0 if there's no current diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index 0a8b3de83c4..ab34d849131 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -801,10 +801,49 @@ last_thread_of_process_p (struct thread_info *thread) second_thread_of_pid_p, &counter) == NULL); } -/* Kill the inferior lwp. */ +/* Kill LWP. */ + +static void +linux_kill_one_lwp (struct lwp_info *lwp) +{ + int pid = lwpid_of (lwp); + + /* PTRACE_KILL is unreliable. After stepping into a signal handler, + there is no signal context, and ptrace(PTRACE_KILL) (or + ptrace(PTRACE_CONT, SIGKILL), pretty much the same) acts like + ptrace(CONT, pid, 0,0) and just resumes the tracee. A better + alternative is to kill with SIGKILL. We only need one SIGKILL + per process, not one for each thread. But since we still support + linuxthreads, and we also support debugging programs using raw + clone without CLONE_THREAD, we send one for each thread. For + years, we used PTRACE_KILL only, so we're being a bit paranoid + about some old kernels where PTRACE_KILL might work better + (dubious if there are any such, but that's why it's paranoia), so + we try SIGKILL first, PTRACE_KILL second, and so we're fine + everywhere. */ + + errno = 0; + kill (pid, SIGKILL); + if (debug_threads) + fprintf (stderr, + "LKL: kill (SIGKILL) %s, 0, 0 (%s)\n", + target_pid_to_str (ptid_of (lwp)), + errno ? strerror (errno) : "OK"); + + errno = 0; + ptrace (PTRACE_KILL, pid, 0, 0); + if (debug_threads) + fprintf (stderr, + "LKL: PTRACE_KILL %s, 0, 0 (%s)\n", + target_pid_to_str (ptid_of (lwp)), + errno ? strerror (errno) : "OK"); +} + +/* Callback for `find_inferior'. Kills an lwp of a given process, + except the leader. */ static int -linux_kill_one_lwp (struct inferior_list_entry *entry, void *args) +kill_one_lwp_callback (struct inferior_list_entry *entry, void *args) { struct thread_info *thread = (struct thread_info *) entry; struct lwp_info *lwp = get_thread_lwp (thread); @@ -829,7 +868,7 @@ linux_kill_one_lwp (struct inferior_list_entry *entry, void *args) do { - ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0); + linux_kill_one_lwp (lwp); /* Make sure it died. The loop is most likely unnecessary. */ pid = linux_wait_for_event (lwp->head.id, &wstat, __WALL); @@ -854,7 +893,7 @@ linux_kill (int pid) first, as PTRACE_KILL will not work otherwise. */ stop_all_lwps (0, NULL); - find_inferior (&all_threads, linux_kill_one_lwp, &pid); + find_inferior (&all_threads, kill_one_lwp_callback , &pid); /* See the comment in linux_kill_one_lwp. We did not kill the first thread in the list, so do so now. */ @@ -874,7 +913,7 @@ linux_kill (int pid) do { - ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0); + linux_kill_one_lwp (lwp); /* Make sure it died. The loop is most likely unnecessary. */ lwpid = linux_wait_for_event (lwp->head.id, &wstat, __WALL); -- 2.30.2