Skip to content

Commit c29705b

Browse files
author
Philippe Waroquiers
committed
Fix internal error and improve 'set debug infrun 1'/target wait kind trace
The test gdb.threads/watchthreads-reorder.exp verifies that the 'set debug infrun 1' debug output does not crash GDB. Under high load, the test can still cause a GDB internal error (see details below). This patch fixes this crash, and improves/factorises some wait kind traces. Tested on debian/amd64 + run one test with 'set debug infrun 1'. Changes compared to the first version: * Handles the suggestions of Kevin to trace the relevant elements of the wait status (this is done by calling target_waitstatus_to_string). * Some other changes to factorise wait status tracing. Note that using target_waitstatus_to_string instead of the 'locally printed' status kind strings means that debug trace that was using strings such as: "EXITED" or "TARGET_WAITKIND_EXITED" will now use what is printed by target_waitstatus_to_string e.g. "exited". gdb/ChangeLog 2019-04-01 Philippe Waroquiers <philippe.waroquiers@skynet.be> * infrun.c (stop_all_threads): If debug_infrun, always trace the wait status after wait_one, using target_waitstatus_to_string and target_pid_to_str. (handle_inferior_event): Replace various trace of wait status kind by a single trace. * gdb/gnu-nat.c (gnu_nat_target::wait): Replace local wait status kind image by target_waitstatus_to_string. * target/waitstatus.c (target_waitstatus_to_string): Fix obsolete comment. (top-gdb) bt #0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51 #1 0x00007f3d54a0642a in __GI_abort () at abort.c:89 #2 0x0000555c24c60e66 in dump_core () at ../../fixleaks/gdb/utils.c:201 #3 0x0000555c24c63d49 in internal_vproblem(internal_problem *, const char *, int, const char *, typedef __va_list_tag __va_list_tag *) (problem=problem@entry=0x555c25338d40 <internal_error_problem>, file=<optimized out>, line=287, fmt=<optimized out>, ap=<optimized out>) at ../../fixleaks/gdb/utils.c:411 #4 0x0000555c24c63eab in internal_verror (file=<optimized out>, line=<optimized out>, fmt=<optimized out>, ap=<optimized out>) at ../../fixleaks/gdb/utils.c:436 #5 0x0000555c249e8c22 in internal_error (file=file@entry=0x555c24e0f2ad "../../fixleaks/gdb/inferior.c", line=line@entry=287, fmt=<optimized out>) at ../../fixleaks/gdb/common/errors.c:55 #6 0x0000555c247d3f5c in find_inferior_pid (pid=<optimized out>) at ../../fixleaks/gdb/inferior.c:287 #7 0x0000555c24ad2248 in find_inferior_pid (pid=<optimized out>) at ../../fixleaks/gdb/inferior.c:302 #8 find_inferior_ptid (ptid=...) at ../../fixleaks/gdb/inferior.c:301 #9 0x0000555c24c35f25 in find_thread_ptid (ptid=...) at ../../fixleaks/gdb/thread.c:522 #10 0x0000555c24b0ab4d in thread_db_target::pid_to_str[abi:cxx11](ptid_t) ( this=0x555c2532e3e0 <the_thread_db_target>, ptid=...) at ../../fixleaks/gdb/linux-thread-db.c:1637 #11 0x0000555c24c2f420 in target_pid_to_str[abi:cxx11](ptid_t) (ptid=...) at ../../fixleaks/gdb/target.c:2083 #12 0x0000555c24ad9cab in stop_all_threads () at ../../fixleaks/gdb/infrun.c:4373 #13 0x0000555c24ada00f in stop_waiting (ecs=<optimized out>) at ../../fixleaks/gdb/infrun.c:7464 #14 0x0000555c24adc401 in process_event_stop_test (ecs=ecs@entry=0x7ffc9402d9d0) at ../../fixleaks/gdb/infrun.c:6181 ... (top-gdb) fr 12 #12 0x0000555c24ad9cab in stop_all_threads () at ../../fixleaks/gdb/infrun.c:4373 (top-gdb) p event_ptid $5 = {m_pid = 25419, m_lwp = 25427, m_tid = 0} (top-gdb) p ptid $6 = {m_pid = 0, m_lwp = 0, m_tid = 0} (top-gdb) p ws $7 = {kind = TARGET_WAITKIND_THREAD_EXITED, value = {integer = 0, sig = GDB_SIGNAL_0, related_pid = {m_pid = 0, m_lwp = 0, m_tid = 0}, execd_pathname = 0x0, syscall_number = 0}} (top-gdb) The gdb.log corresponding to the above crash is: (gdb) PASS: gdb.threads/watchthreads-reorder.exp: reorder1: set debug infrun 1 continue Continuing. infrun: clear_proceed_status_thread (Thread 0x7ffff7fcfb40 (LWP 25419)) infrun: clear_proceed_status_thread (Thread 0x7ffff7310700 (LWP 25427)) infrun: clear_proceed_status_thread (Thread 0x7ffff6b0f700 (LWP 25428)) infrun: proceed (addr=0xffffffffffffffff, signal=GDB_SIGNAL_DEFAULT) infrun: proceed: resuming Thread 0x7ffff7fcfb40 (LWP 25419) infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [Thread 0x7ffff7fcfb40 (LWP 25419)] at 0x7ffff7344317 infrun: infrun_async(1) infrun: prepare_to_wait infrun: proceed: resuming Thread 0x7ffff7310700 (LWP 25427) infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [Thread 0x7ffff7310700 (LWP 25427)] at 0x5555555553d7 infrun: prepare_to_wait infrun: proceed: resuming Thread 0x7ffff6b0f700 (LWP 25428) infrun: resume (step=0, signal=GDB_SIGNAL_0), trap_expected=0, current thread [Thread 0x7ffff6b0f700 (LWP 25428)] at 0x5555555554c8 infrun: prepare_to_wait infrun: target_wait (-1.0.0, status) = infrun: -1.0.0 [process -1], infrun: status->kind = ignore infrun: TARGET_WAITKIND_IGNORE infrun: prepare_to_wait Joining the threads. [Thread 0x7ffff6b0f700 (LWP 25428) exited] infrun: target_wait (-1.0.0, status) = infrun: -1.0.0 [process -1], infrun: status->kind = ignore infrun: TARGET_WAITKIND_IGNORE infrun: prepare_to_wait infrun: target_wait (-1.0.0, status) = infrun: 25419.25419.0 [Thread 0x7ffff7fcfb40 (LWP 25419)], infrun: status->kind = stopped, signal = GDB_SIGNAL_TRAP infrun: TARGET_WAITKIND_STOPPED infrun: stop_pc = 0x555555555e50 infrun: context switch infrun: Switching context from Thread 0x7ffff6b0f700 (LWP 25428) to Thread 0x7ffff7fcfb40 (LWP 25419) infrun: BPSTAT_WHAT_STOP_NOISY infrun: stop_waiting infrun: stop_all_threads infrun: stop_all_threads, pass=0, iterations=0 infrun: Thread 0x7ffff7fcfb40 (LWP 25419) not executing infrun: Thread 0x7ffff7310700 (LWP 25427) executing, need stop [Thread 0x7ffff7310700 (LWP 25427) exited] infrun: target_wait (-1.0.0, status) = infrun: 25419.25427.0 [LWP 25427], infrun: status->kind = thread exited, status = 0 infrun: infrun_async(0) ../../fixleaks/gdb/inferior.c:287: internal-error: inferior* find_inferior_pid(int): Assertion `pid != 0' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) FAIL: gdb.threads/watchthreads-reorder.exp: reorder1: continue to breakpoint: break-at-exit (GDB internal error) Resyncing due to internal error. n infrun: infrun_async(1) This is a bug, please report it. For instructions, see: <http://www.gnu.org/software/gdb/bugs/>. infrun: infrun_async(0) ../../fixleaks/gdb/inferior.c:287: internal-error: inferior* find_inferior_pid(int): Assertion `pid != 0' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Create a core file of GDB? (y or n) y
1 parent 05caa1d commit c29705b

File tree

4 files changed

+31
-72
lines changed

4 files changed

+31
-72
lines changed

Diff for: gdb/ChangeLog

+12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
2019-04-01 Philippe Waroquiers <philippe.waroquiers@skynet.be>
2+
3+
* infrun.c (stop_all_threads): If debug_infrun, always
4+
trace the wait status after wait_one, using
5+
target_waitstatus_to_string and target_pid_to_str.
6+
(handle_inferior_event): Replace various trace of
7+
wait status kind by a single trace.
8+
* gdb/gnu-nat.c (gnu_nat_target::wait): Replace local
9+
wait status kind image by target_waitstatus_to_string.
10+
* target/waitstatus.c (target_waitstatus_to_string): Fix
11+
obsolete comment.
12+
113
2019-04-01 Tom Tromey <tromey@adacore.com>
214

315
PR symtab/23331:

Diff for: gdb/gnu-nat.c

+2-8
Original file line numberDiff line numberDiff line change
@@ -1647,15 +1647,9 @@ gnu_nat_target::wait (ptid_t ptid, struct target_waitstatus *status,
16471647
inf_update_suspends (inf);
16481648
}
16491649

1650-
inf_debug (inf, "returning ptid = %s, status = %s (%d)",
1650+
inf_debug (inf, "returning ptid = %s, %s",
16511651
target_pid_to_str (ptid).c_str (),
1652-
status->kind == TARGET_WAITKIND_EXITED ? "EXITED"
1653-
: status->kind == TARGET_WAITKIND_STOPPED ? "STOPPED"
1654-
: status->kind == TARGET_WAITKIND_SIGNALLED ? "SIGNALLED"
1655-
: status->kind == TARGET_WAITKIND_LOADED ? "LOADED"
1656-
: status->kind == TARGET_WAITKIND_SPURIOUS ? "SPURIOUS"
1657-
: "?",
1658-
status->value.integer);
1652+
target_waitstatus_to_string (&status).c_str ());
16591653

16601654
return ptid;
16611655
}

Diff for: gdb/infrun.c

+16-62
Original file line numberDiff line numberDiff line change
@@ -4358,24 +4358,21 @@ stop_all_threads (void)
43584358
pass = -1;
43594359

43604360
event_ptid = wait_one (&ws);
4361-
4362-
if (ws.kind == TARGET_WAITKIND_NO_RESUMED)
4361+
if (debug_infrun)
43634362
{
4364-
/* All resumed threads exited. */
4363+
fprintf_unfiltered (gdb_stdlog,
4364+
"infrun: stop_all_threads %s %s\n",
4365+
target_waitstatus_to_string (&ws).c_str (),
4366+
target_pid_to_str (event_ptid).c_str ());
43654367
}
4366-
else if (ws.kind == TARGET_WAITKIND_THREAD_EXITED
4367-
|| ws.kind == TARGET_WAITKIND_EXITED
4368-
|| ws.kind == TARGET_WAITKIND_SIGNALLED)
4369-
{
4370-
if (debug_infrun)
4371-
{
4372-
ptid_t ptid = ptid_t (ws.value.integer);
43734368

4374-
fprintf_unfiltered (gdb_stdlog,
4375-
"infrun: %s exited while "
4376-
"stopping threads\n",
4377-
target_pid_to_str (ptid).c_str ());
4378-
}
4369+
if (ws.kind == TARGET_WAITKIND_NO_RESUMED
4370+
|| ws.kind == TARGET_WAITKIND_THREAD_EXITED
4371+
|| ws.kind == TARGET_WAITKIND_EXITED
4372+
|| ws.kind == TARGET_WAITKIND_SIGNALLED)
4373+
{
4374+
/* All resumed threads exited
4375+
or one thread/process exited/signalled. */
43794376
}
43804377
else
43814378
{
@@ -4604,6 +4601,10 @@ handle_inferior_event (struct execution_control_state *ecs)
46044601

46054602
enum stop_kind stop_soon;
46064603

4604+
if (debug_infrun)
4605+
fprintf_unfiltered (gdb_stdlog, "infrun: handle_inferior_event %s\n",
4606+
target_waitstatus_to_string (&ecs->ws).c_str ());
4607+
46074608
if (ecs->ws.kind == TARGET_WAITKIND_IGNORE)
46084609
{
46094610
/* We had an event in the inferior, but we are not interested in
@@ -4615,16 +4616,12 @@ handle_inferior_event (struct execution_control_state *ecs)
46154616
not stopped, and we are ignoring the event. Another possible
46164617
circumstance is any event which the lower level knows will be
46174618
reported multiple times without an intervening resume. */
4618-
if (debug_infrun)
4619-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_IGNORE\n");
46204619
prepare_to_wait (ecs);
46214620
return;
46224621
}
46234622

46244623
if (ecs->ws.kind == TARGET_WAITKIND_THREAD_EXITED)
46254624
{
4626-
if (debug_infrun)
4627-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_EXITED\n");
46284625
prepare_to_wait (ecs);
46294626
return;
46304627
}
@@ -4643,9 +4640,6 @@ handle_inferior_event (struct execution_control_state *ecs)
46434640
{
46444641
/* No unwaited-for children left. IOW, all resumed children
46454642
have exited. */
4646-
if (debug_infrun)
4647-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_RESUMED\n");
4648-
46494643
stop_print_frame = 0;
46504644
stop_waiting (ecs);
46514645
return;
@@ -4738,8 +4732,6 @@ handle_inferior_event (struct execution_control_state *ecs)
47384732
switch (ecs->ws.kind)
47394733
{
47404734
case TARGET_WAITKIND_LOADED:
4741-
if (debug_infrun)
4742-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_LOADED\n");
47434735
context_switch (ecs);
47444736
/* Ignore gracefully during startup of the inferior, as it might
47454737
be the shell which has just loaded some objects, otherwise
@@ -4817,8 +4809,6 @@ handle_inferior_event (struct execution_control_state *ecs)
48174809
_("unhandled stop_soon: %d"), (int) stop_soon);
48184810

48194811
case TARGET_WAITKIND_SPURIOUS:
4820-
if (debug_infrun)
4821-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_SPURIOUS\n");
48224812
if (handle_stop_requested (ecs))
48234813
return;
48244814
context_switch (ecs);
@@ -4827,8 +4817,6 @@ handle_inferior_event (struct execution_control_state *ecs)
48274817
return;
48284818

48294819
case TARGET_WAITKIND_THREAD_CREATED:
4830-
if (debug_infrun)
4831-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_THREAD_CREATED\n");
48324820
if (handle_stop_requested (ecs))
48334821
return;
48344822
context_switch (ecs);
@@ -4838,16 +4826,6 @@ handle_inferior_event (struct execution_control_state *ecs)
48384826

48394827
case TARGET_WAITKIND_EXITED:
48404828
case TARGET_WAITKIND_SIGNALLED:
4841-
if (debug_infrun)
4842-
{
4843-
if (ecs->ws.kind == TARGET_WAITKIND_EXITED)
4844-
fprintf_unfiltered (gdb_stdlog,
4845-
"infrun: TARGET_WAITKIND_EXITED\n");
4846-
else
4847-
fprintf_unfiltered (gdb_stdlog,
4848-
"infrun: TARGET_WAITKIND_SIGNALLED\n");
4849-
}
4850-
48514829
inferior_ptid = ecs->ptid;
48524830
set_current_inferior (find_inferior_ptid (ecs->ptid));
48534831
set_current_program_space (current_inferior ()->pspace);
@@ -4912,14 +4890,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
49124890
the above cases end in a continue or goto. */
49134891
case TARGET_WAITKIND_FORKED:
49144892
case TARGET_WAITKIND_VFORKED:
4915-
if (debug_infrun)
4916-
{
4917-
if (ecs->ws.kind == TARGET_WAITKIND_FORKED)
4918-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_FORKED\n");
4919-
else
4920-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_VFORKED\n");
4921-
}
4922-
49234893
/* Check whether the inferior is displaced stepping. */
49244894
{
49254895
struct regcache *regcache = get_thread_regcache (ecs->event_thread);
@@ -5080,10 +5050,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
50805050
/* Done with the shared memory region. Re-insert breakpoints in
50815051
the parent, and keep going. */
50825052

5083-
if (debug_infrun)
5084-
fprintf_unfiltered (gdb_stdlog,
5085-
"infrun: TARGET_WAITKIND_VFORK_DONE\n");
5086-
50875053
context_switch (ecs);
50885054

50895055
current_inferior ()->waiting_for_vfork_done = 0;
@@ -5098,8 +5064,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
50985064
return;
50995065

51005066
case TARGET_WAITKIND_EXECD:
5101-
if (debug_infrun)
5102-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_EXECD\n");
51035067

51045068
/* Note we can't read registers yet (the stop_pc), because we
51055069
don't yet know the inferior's post-exec architecture.
@@ -5148,9 +5112,6 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
51485112
/* Be careful not to try to gather much state about a thread
51495113
that's in a syscall. It's frequently a losing proposition. */
51505114
case TARGET_WAITKIND_SYSCALL_ENTRY:
5151-
if (debug_infrun)
5152-
fprintf_unfiltered (gdb_stdlog,
5153-
"infrun: TARGET_WAITKIND_SYSCALL_ENTRY\n");
51545115
/* Getting the current syscall number. */
51555116
if (handle_syscall_event (ecs) == 0)
51565117
process_event_stop_test (ecs);
@@ -5162,22 +5123,15 @@ Cannot fill $_exitsignal with the correct signal number.\n"));
51625123
syscall. Stepping one instruction seems to get it back
51635124
into user code.) */
51645125
case TARGET_WAITKIND_SYSCALL_RETURN:
5165-
if (debug_infrun)
5166-
fprintf_unfiltered (gdb_stdlog,
5167-
"infrun: TARGET_WAITKIND_SYSCALL_RETURN\n");
51685126
if (handle_syscall_event (ecs) == 0)
51695127
process_event_stop_test (ecs);
51705128
return;
51715129

51725130
case TARGET_WAITKIND_STOPPED:
5173-
if (debug_infrun)
5174-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_STOPPED\n");
51755131
handle_signal_stop (ecs);
51765132
return;
51775133

51785134
case TARGET_WAITKIND_NO_HISTORY:
5179-
if (debug_infrun)
5180-
fprintf_unfiltered (gdb_stdlog, "infrun: TARGET_WAITKIND_NO_HISTORY\n");
51815135
/* Reverse execution: target ran out of history info. */
51825136

51835137
/* Switch to the stopped thread. */

Diff for: gdb/target/waitstatus.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
#include "common/common-defs.h"
2121
#include "waitstatus.h"
2222

23-
/* Return a pretty printed form of target_waitstatus.
24-
Space for the result is malloc'd, caller must free. */
23+
/* Return a pretty printed form of target_waitstatus. */
2524

2625
std::string
2726
target_waitstatus_to_string (const struct target_waitstatus *ws)

0 commit comments

Comments
 (0)