@@ -1447,6 +1447,39 @@ get_detach_signal (struct thread_info *thread)
}
}
+/* Called when we try to resume or detach a stopped LWP and that errors
+ out. If the LWP is no longer in ptrace-stopped state (meaning it's
+ zombie, or about to become), discard the error, clear any pending
+ status the LWP may have, and return true (we'll collect the exit status
+ soon enough). Otherwise, return false. */
+
+static int
+check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
+{
+ struct thread_info *thread = get_lwp_thread (lp);
+
+ /* If we get an error after resuming the LWP successfully, we'd
+ confuse !T state for the LWP being gone. */
+ gdb_assert (lp->stopped);
+
+ /* We can't just check whether the LWP is in 'Z (Zombie)' state,
+ because even if ptrace failed with ESRCH, the tracee may be "not
+ yet fully dead", but already refusing ptrace requests. In that
+ case the tracee has 'R (Running)' state for a little bit
+ (observed in Linux 3.18). See also the note on ESRCH in the
+ ptrace(2) man page. Instead, check whether the LWP has any state
+ other than ptrace-stopped. */
+
+ /* Don't assume anything if /proc/PID/status can't be read. */
+ if (linux_proc_pid_is_trace_stopped_nowarn (lwpid_of (thread)) == 0)
+ {
+ lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+ lp->status_pending_p = 0;
+ return 1;
+ }
+ return 0;
+}
+
static int
linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
{
@@ -1480,9 +1513,10 @@ linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
the_low_target.prepare_to_resume (lwp);
if (ptrace (PTRACE_DETACH, lwpid_of (thread), (PTRACE_TYPE_ARG3) 0,
(PTRACE_TYPE_ARG4) (long) sig) < 0)
- error (_("Can't detach %s: %s"),
- target_pid_to_str (ptid_of (thread)),
- strerror (errno));
+ if (!check_ptrace_stopped_lwp_gone (lwp))
+ error (_("Can't detach %s: %s"),
+ target_pid_to_str (ptid_of (thread)),
+ strerror (errno));
delete_lwp (lwp);
return 0;
@@ -4331,39 +4365,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
lwp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
}
-/* Called when we try to resume a stopped LWP and that errors out. If
- the LWP is no longer in ptrace-stopped state (meaning it's zombie,
- or about to become), discard the error, clear any pending status
- the LWP may have, and return true (we'll collect the exit status
- soon enough). Otherwise, return false. */
-
-static int
-check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
-{
- struct thread_info *thread = get_lwp_thread (lp);
-
- /* If we get an error after resuming the LWP successfully, we'd
- confuse !T state for the LWP being gone. */
- gdb_assert (lp->stopped);
-
- /* We can't just check whether the LWP is in 'Z (Zombie)' state,
- because even if ptrace failed with ESRCH, the tracee may be "not
- yet fully dead", but already refusing ptrace requests. In that
- case the tracee has 'R (Running)' state for a little bit
- (observed in Linux 3.18). See also the note on ESRCH in the
- ptrace(2) man page. Instead, check whether the LWP has any state
- other than ptrace-stopped. */
-
- /* Don't assume anything if /proc/PID/status can't be read. */
- if (linux_proc_pid_is_trace_stopped_nowarn (lwpid_of (thread)) == 0)
- {
- lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
- lp->status_pending_p = 0;
- return 1;
- }
- return 0;
-}
-
/* Like linux_resume_one_lwp_throw, but no error is thrown if the LWP
disappears while we try to resume it. */
@@ -31,6 +31,7 @@
#include "inf-ptrace.h"
#include "inf-child.h"
#include "gdbthread.h"
+#include "nat/linux-procfs.h"
@@ -259,7 +260,10 @@ inf_ptrace_detach (struct target_ops *ops, const char *args, int from_tty)
started the process ourselves. */
errno = 0;
ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, sig);
- if (errno != 0)
+
+ /* Don't consider the error if /proc/PID/status can't be read.
+ See check_ptrace_stopped_lwp_gone. */
+ if (errno != 0 && linux_proc_pid_is_trace_stopped_nowarn (pid) != 0)
perror_with_name (("ptrace"));
#else
error (_("This system does not support detaching from a process"));
@@ -1382,6 +1382,38 @@ get_pending_status (struct lwp_info *lp, int *status)
return 0;
}
+/* Called when we try to resume or detach a stopped LWP and that errors
+ out. If the LWP is no longer in ptrace-stopped state (meaning it's
+ zombie, or about to become), discard the error, clear any pending
+ status the LWP may have, and return true (we'll collect the exit status
+ soon enough). Otherwise, return false. */
+
+static int
+check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
+{
+ /* If we get an error after resuming the LWP successfully, we'd
+ confuse !T state for the LWP being gone. */
+ gdb_assert (lp->stopped);
+
+ /* We can't just check whether the LWP is in 'Z (Zombie)' state,
+ because even if ptrace failed with ESRCH, the tracee may be "not
+ yet fully dead", but already refusing ptrace requests. In that
+ case the tracee has 'R (Running)' state for a little bit
+ (observed in Linux 3.18). See also the note on ESRCH in the
+ ptrace(2) man page. Instead, check whether the LWP has any state
+ other than ptrace-stopped. */
+
+ /* Don't assume anything if /proc/PID/status can't be read. */
+ if (linux_proc_pid_is_trace_stopped_nowarn (ptid_get_lwp (lp->ptid)) == 0)
+ {
+ lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
+ lp->status = 0;
+ lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+ return 1;
+ }
+ return 0;
+}
+
static int
detach_callback (struct lwp_info *lp, void *data)
{
@@ -1418,8 +1450,9 @@ detach_callback (struct lwp_info *lp, void *data)
errno = 0;
if (ptrace (PTRACE_DETACH, ptid_get_lwp (lp->ptid), 0,
WSTOPSIG (status)) < 0)
- error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid),
- safe_strerror (errno));
+ if (!check_ptrace_stopped_lwp_gone (lp))
+ error (_("Can't detach %s: %s"), target_pid_to_str (lp->ptid),
+ safe_strerror (errno));
if (debug_linux_nat)
fprintf_unfiltered (gdb_stdlog,
@@ -1531,38 +1564,6 @@ linux_resume_one_lwp_throw (struct lwp_info *lp, int step,
registers_changed_ptid (lp->ptid);
}
-/* Called when we try to resume a stopped LWP and that errors out. If
- the LWP is no longer in ptrace-stopped state (meaning it's zombie,
- or about to become), discard the error, clear any pending status
- the LWP may have, and return true (we'll collect the exit status
- soon enough). Otherwise, return false. */
-
-static int
-check_ptrace_stopped_lwp_gone (struct lwp_info *lp)
-{
- /* If we get an error after resuming the LWP successfully, we'd
- confuse !T state for the LWP being gone. */
- gdb_assert (lp->stopped);
-
- /* We can't just check whether the LWP is in 'Z (Zombie)' state,
- because even if ptrace failed with ESRCH, the tracee may be "not
- yet fully dead", but already refusing ptrace requests. In that
- case the tracee has 'R (Running)' state for a little bit
- (observed in Linux 3.18). See also the note on ESRCH in the
- ptrace(2) man page. Instead, check whether the LWP has any state
- other than ptrace-stopped. */
-
- /* Don't assume anything if /proc/PID/status can't be read. */
- if (linux_proc_pid_is_trace_stopped_nowarn (ptid_get_lwp (lp->ptid)) == 0)
- {
- lp->stop_reason = TARGET_STOPPED_BY_NO_REASON;
- lp->status = 0;
- lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
- return 1;
- }
- return 0;
-}
-
/* Like linux_resume_one_lwp_throw, but no error is thrown if the LWP
disappears while we try to resume it. */
new file mode 100644
@@ -0,0 +1,45 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2016 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <pthread.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+pthread_barrier_t barrier;
+
+void *
+child_function (void *arg)
+{
+ pthread_barrier_wait (&barrier);
+ _exit(0);
+}
+
+int
+main ()
+{
+ pthread_t threads[256];
+ int res;
+ int i;
+
+ pthread_barrier_init (&barrier, NULL, 257);
+
+ for (i = 0; i < 256; i++)
+ res = pthread_create (&threads[i], NULL, child_function, NULL);
+
+ pthread_barrier_wait (&barrier);
+ exit(0);
+}
new file mode 100644
@@ -0,0 +1,37 @@
+# Copyright 2015-2016 Free Software Foundation, Inc.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+if ![runto_main] {
+ fail "Can't run to main to check for trace support"
+ return -1
+}
+
+if $use_gdb_stub {
+ # This test is about testing detaching from a process,
+ # so it doesn't make sense to run it if the target is stub-like.
+ unsupported "This test is not supported for GDB stub targets."
+ return -1
+}
+
+gdb_breakpoint "_exit"
+gdb_continue_to_breakpoint "_exit" ".*_exit.*"
+gdb_test "detach" "Detaching from .*, process $decimal"