This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[PATCH] Fix staticthreads test case with merged Linux targets
- From: "Ulrich Weigand" <uweigand at de dot ibm dot com>
- To: gdb-patches at sources dot redhat dot com
- Date: Thu, 6 Apr 2006 02:34:19 +0200 (CEST)
- Subject: [PATCH] Fix staticthreads test case with merged Linux targets
Hello,
another problem triggered by Linux target rework: the staticthreads
test case hangs. This is because when the thread-db handling does
not work properly (because the statically linked inferior uses
LinuxThreads, while the dynamically linked gdb expects NPTL), we
still get informed of clone events; the kernel then automatically
attaches gdb to the new clone as well. What the old child_wait
function did in this case was to simply detach again and leave
the new clone alone.
With the merged Linux targets, linux_nat_handle_extended gets
invoked and simply adds the new clone to the LWP list. However,
it not only does not detach from the new clone, it also does
not *continue* it.
Now, when linux_nat_handle_extended is invoked from within
stop_wait_callback (via wait_lwp), this is likely the correct
behaviour -- we are currenly in the process of stopping all
LWPs, so the new one should be stopped as well. It will be
continued when we resume all LWPs.
However, when linux_nat_handle_extended is invoked from within
linux_nat_wait, that function will simply continue waiting on
the inferior, without resuming the new clone.
In the staticthreads test case, this deadlocks: gdb waits on
an event on the initial thread of the inferior, which is blocked
on waiting for the new thread -- which never started up.
Now, I'm not sure how the whole treatment of LWPs in the absence
of thread-db is really supposed to work. However, the following
patch appears reasonable to me and does fix the test case. What
the patch does is to simply add an argument to linux_nat_handle_extended
whether it should leave the new clone stopped or resume it. The
two callers can then choose the proper behaviour.
This exposed another bug in exit_lwp: if one such LWP exists, it
may have never been on the main thread list -- in that case the
exit_lwp code accesses a NULL pointer. The fix should be obvious.
Tested on s390-ibm-linux and s390x-ibm-linux without regressions.
OK for mainline?
Bye,
Ulrich
ChangeLog:
* linux-nat.c (exit_lwp): Fix NULL pointer access.
(linux_nat_handle_extended): New parameter STOPPING.
(wait_lwp): Call it with STOPPING equals 1.
(linux_nat_wait): Call it with STOPPING equals 0.
Index: gdb/linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-nat.c,v
retrieving revision 1.41
diff -c -p -r1.41 linux-nat.c
*** gdb/linux-nat.c 30 Mar 2006 16:34:23 -0000 1.41
--- gdb/linux-nat.c 6 Apr 2006 00:17:46 -0000
*************** exit_lwp (struct lwp_info *lp)
*** 899,908 ****
struct thread_info *thr;
thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid);
! if (thr && !ptid_equal (thr->ptid, inferior_ptid))
! delete_thread (thr->ptid);
! else
! record_dead_thread (thr->ptid);
}
delete_lwp (lp->ptid);
--- 899,911 ----
struct thread_info *thr;
thr = iterate_over_threads (find_thread_from_lwp, &lp->ptid);
! if (thr)
! {
! if (!ptid_equal (thr->ptid, inferior_ptid))
! delete_thread (thr->ptid);
! else
! record_dead_thread (thr->ptid);
! }
}
delete_lwp (lp->ptid);
*************** kill_lwp (int lwpid, int signo)
*** 1278,1287 ****
just pass off to linux_handle_extended_wait, but if it reports a
clone event we need to add the new LWP to our list (and not report
the trap to higher layers). This function returns non-zero if
! the event should be ignored and we should wait again. */
static int
! linux_nat_handle_extended (struct lwp_info *lp, int status)
{
linux_handle_extended_wait (GET_LWP (lp->ptid), status,
&lp->waitstatus);
--- 1281,1291 ----
just pass off to linux_handle_extended_wait, but if it reports a
clone event we need to add the new LWP to our list (and not report
the trap to higher layers). This function returns non-zero if
! the event should be ignored and we should wait again. If STOPPING
! is true, the new LWP remains stopped, otherwise it is continued. */
static int
! linux_nat_handle_extended (struct lwp_info *lp, int status, int stopping)
{
linux_handle_extended_wait (GET_LWP (lp->ptid), status,
&lp->waitstatus);
*************** linux_nat_handle_extended (struct lwp_in
*** 1293,1299 ****
new_lp = add_lwp (BUILD_LWP (lp->waitstatus.value.related_pid,
GET_PID (inferior_ptid)));
new_lp->cloned = 1;
! new_lp->stopped = 1;
lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
--- 1297,1307 ----
new_lp = add_lwp (BUILD_LWP (lp->waitstatus.value.related_pid,
GET_PID (inferior_ptid)));
new_lp->cloned = 1;
!
! if (stopping)
! new_lp->stopped = 1;
! else
! ptrace (PTRACE_CONT, lp->waitstatus.value.related_pid, 0, 0);
lp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
*************** wait_lwp (struct lwp_info *lp)
*** 1377,1383 ****
fprintf_unfiltered (gdb_stdlog,
"WL: Handling extended status 0x%06x\n",
status);
! if (linux_nat_handle_extended (lp, status))
return wait_lwp (lp);
}
--- 1385,1391 ----
fprintf_unfiltered (gdb_stdlog,
"WL: Handling extended status 0x%06x\n",
status);
! if (linux_nat_handle_extended (lp, status, 1))
return wait_lwp (lp);
}
*************** retry:
*** 2022,2028 ****
fprintf_unfiltered (gdb_stdlog,
"LLW: Handling extended status 0x%06x\n",
status);
! if (linux_nat_handle_extended (lp, status))
{
status = 0;
continue;
--- 2030,2036 ----
fprintf_unfiltered (gdb_stdlog,
"LLW: Handling extended status 0x%06x\n",
status);
! if (linux_nat_handle_extended (lp, status, 0))
{
status = 0;
continue;
--
Dr. Ulrich Weigand
Linux on zSeries Development
Ulrich.Weigand@de.ibm.com