This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] gdbserver: Set flag `suspended' properly for new lwp.


Occasionally I see the following fails when run it with `target-async on'
and native-gdbserver.exp board file:

Running ../../../gdb/gdb/testsuite/gdb.mi/mi-nsmoribund.exp ...
FAIL: gdb.mi/mi-nsmoribund.exp: stop 0 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 1 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 2 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 3 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 4 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 5 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 6 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 7 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 8 (timeout)
FAIL: gdb.mi/mi-nsmoribund.exp: stop 9 (timeout)

../../../gdb/gdb/gdbserver/linux-low.c:3891: A problem internal to GDBserver has been detected.^M
unsuspend_and_proceed_one_lwp: Assertion `lwp->suspended >= 0' failed.^

The problem is a lwp is added during step over tracepoint/breakpoint,
but its `suspended' flag is not set properly.

(gdb) bt
 #0  add_lwp (ptid=...) at ../../../../gdb/gdb/gdbserver/linux-low.c:569
 #1  0x08068ab2 in handle_extended_wait (wstat=<optimized out>, event_child=<optimized out>) at ../../../../gdb/gdb/gdbserver/linux-low.c:455
 #2  linux_wait_for_event (ptid=..., wstat=0xbfffeedc, options=1073741824) at ../../../../gdb/gdb/gdbserver/linux-low.c:1951
 #3  0x08068c31 in wait_for_sigstop (entry=0x808d1d8) at ../../../../gdb/gdb/gdbserver/linux-low.c:2930
 #4  0x0804ccd0 in for_each_inferior (list=0x80840d8, action=0x8068ba0 <wait_for_sigstop>) at ../../../../gdb/gdb/gdbserver/inferiors.c:57
 #5  0x08062fc0 in stop_all_lwps (suspend=<optimized out>, except=<optimized out>) at ../../../../gdb/gdb/gdbserver/linux-low.c:3081
 #6  0x08067774 in start_step_over (lwp=0x808e7c0) at ../../../../gdb/gdb/gdbserver/linux-low.c:3546
 #7  0x08069751 in proceed_all_lwps () at ../../../../gdb/gdb/gdbserver/linux-low.c:3923

later, when GDBserver unsuspends the new lwp, the internal error is emitted.

(gdb) bt
 #0  internal_error (file=0x807b9ac "../../../../gdb/gdb/gdbserver/linux-low.c", line=2152, fmt=0x807436f "%s: Assertion `%s' failed.") at ../../../../gdb/gdb/gdbserver/utils.c:161
 #1  0x08062d2b in unsuspend_one_lwp (entry=0x808ea00, except=0x808e7c0) at ../../../../gdb/gdb/gdbserver/linux-low.c:2152
 #2  0x0804cd9b in find_inferior (list=0x80840d8, func=0x8062ce0 <unsuspend_one_lwp>, arg=0x808e7c0) at ../../../../gdb/gdb/gdbserver/inferiors.c:183
 #3  0x08069bc8 in unsuspend_all_lwps (except=<optimized out>) at ../../../../gdb/gdb/gdbserver/linux-low.c:2162

This patch is to propagate `suspended' flag to new lwp.  The patch is
short, but not that simple.  I leave some comments.  Please pay
attention to these comments.

gdb/gdbserver:

2012-05-07  Yao Qi  <yao@codesourcery.com>

	* linux-low.c (handle_extended_wait): Set new_lwp's field
	`suspended'.
---
 gdb/gdbserver/linux-low.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index bbb0693..2cfb434 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -461,6 +461,22 @@ handle_extended_wait (struct lwp_info *event_child, int wstat)
 	 before calling linux_resume_one_lwp.  */
       new_lwp->stopped = 1;
 
+      /* When `stopping_threads' is 1, it means GDBserver is stopping
+	 all lwps (see stop_all_lwps).  So there is a new lwp added
+	 during this all-lwps stopping, and its `suspended' flag should
+	 be set carefully.  We are using EVENT_CHILD's `suspend' to
+	 determine all lwps are stopped with suspended or stopped without
+	 suspended.  Note that the lwp EXCEPT(the 2nd parameter of
+	 stop_all_lwps)'s `suspended' flag can be zero, even GDBserver is
+	 stop-with-suspend all lwp, but there should be no event for lwp
+	 EXCEPT (that is to say, EXCEPT != EVENT_CHILD), because it is
+	 not SIGSTOP'ed at all.  We are correct here.
+	 Even GDBserver stop-without-suspend all lwps, but EVENT_CHILD's
+	 `suspended' flag is non-zero, we'll set new lwp's `suspended to
+	 1.  It also looks correct.  '*/
+      if (stopping_threads)
+	new_lwp->suspended = event_child->suspended ? 1 : 0;
+
       /* Normally we will get the pending SIGSTOP.  But in some cases
 	 we might get another signal delivered to the group first.
 	 If we do get another signal, be sure not to lose it.  */
-- 
1.7.0.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]