9c02b52532
Running the testsuite with a series that reimplements user-visible
all-stop behavior on top of a target running in non-stop mode revealed
problems related to event starvation avoidance.
For example, I see
gdb.threads/signal-while-stepping-over-bp-other-thread.exp failing.
What happens is that GDB core never gets to see the signal event. It
ends up processing the events for the same threads over an over,
because Linux's waitpid(-1, ...) returns that first task in the task
list that has an event, starving threads on the tail of the task list.
So I wrote a non-stop mode test originally inspired by
signal-while-stepping-over-bp-other-thread.exp, to stress this
independently of all-stop on top of non-stop. Fixing it required the
changes described below. The test will be added in a following
commit.
1) linux-nat.c has code in place that picks an event LWP at random out
of all that have had events. This is because on the kernel side,
"waitpid(-1, ...)" just walks the task list linearly looking for the
first that had an event. But, this code is currently only used in
all-stop mode. So with a multi-threaded program that has multiple
events triggering debug events in parallel, GDB ends up starving some
threads.
To make the event randomization work in non-stop mode too, the patch
makes us pull out all the already pending events on the kernel side,
with waitpid, before deciding which LWP to report to the core.
There's some code in linux_wait that takes care of leaving events
pending if they were for LWPs the caller is not interested in. The
patch moves that to linux_nat_filter_event, so that we only have one
place that leaves events pending. With that in place, conceptually,
the flow is simpler and more normalized:
#1 - walk the LWP list looking for an LWP with a pending event to report.
#2 - if no pending event, pull events out of the kernel, and store
them in the LWP structures as pending.
#3- goto #1.
2) Then, currently the event randomization code only considers SIGTRAP
(or trap-like) events. That means that if e.g., have have multiple
threads stepping in parallel that hit a breakpoint that needs stepping
over, and one gets a signal, the signal may end up never getting
processed, because GDB will always be giving priority to the SIGTRAPs.
The patch fixes this by making the randomization code consider all
kinds of pending events.
3) If multiple threads hit a breakpoint, we report one of those, and
"cancel" the others. Cancelling means decrementing the PC, and
discarding the event. If the next time the LWP is resumed the
breakpoint is still installed, the LWP should hit it again, and we'll
report the hit then. The problem I found is that this delays threads
from advancing too much, with the kernel potentially ending up
scheduling the same threads over and over, and others not advancing.
So the patch switches away from cancelling the breakpoints, and
instead remembering that the LWP had stopped for a breakpoint. If on
resume the breakpoint is still installed, we report it. If it's no
longer installed, we discard the pending event then. This is actually
how GDBserver used to handle this before d50171e4
(Teach linux
gdbserver to step-over-breakpoints), but with the difference that back
then we'd delay adjusting the PC until resuming, which made it so that
"info threads" could wrongly see threads with unadjusted PCs.
gdb/
2015-01-09 Pedro Alves <palves@redhat.com>
* breakpoint.c (hardware_breakpoint_inserted_here_p): New
function.
* breakpoint.h (hardware_breakpoint_inserted_here_p): New
declaration.
* linux-nat.c (linux_nat_status_is_event): Move higher up in file.
(linux_resume_one_lwp): Store the thread's PC. Adjust to clear
stop_reason.
(check_stopped_by_watchpoint): New function.
(save_sigtrap): Reimplement.
(linux_nat_stopped_by_watchpoint): Adjust.
(linux_nat_lp_status_is_event): Delete.
(stop_wait_callback): Only call save_sigtrap after storing the
pending status.
(status_callback): If the thread had been stopped for a breakpoint
that has since been removed, discard the event and resume the LWP.
(count_events_callback, select_event_lwp_callback): Use
lwp_status_pending_p instead of linux_nat_lp_status_is_event.
(cancel_breakpoint): Rename to ...
(check_stopped_by_breakpoint): ... this. Record whether the LWP
stopped for a software breakpoint or hardware breakpoint.
(select_event_lwp): Only give preference to the stepping LWP in
all-stop mode. Adjust comments.
(stop_and_resume_callback): Remove references to new_pending_p.
(linux_nat_filter_event): Likewise. Leave exit events of the
leader thread pending here. Handle signal short circuiting here.
Only call save_sigtrap after storing the pending waitstatus.
(linux_nat_wait_1): Remove 'retry' label. Remove references to
new_pending. Don't handle leaving events the caller is not
interested in pending here, nor handle signal short-circuiting
here. Also give equal priority to all LWPs that have had events
in non-stop mode. If reporting a software breakpoint event,
unadjust the LWP's PC.
* linux-nat.h (enum lwp_stop_reason): New.
(struct lwp_info) <stop_pc>: New field.
(struct lwp_info) <stopped_by_watchpoint>: Delete field.
(struct lwp_info) <stop_reason>: New field.
* x86-linux-nat.c (x86_linux_prepare_to_resume): Adjust.
232 lines
8.4 KiB
Text
232 lines
8.4 KiB
Text
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* breakpoint.c (hardware_breakpoint_inserted_here_p): New
|
||
function.
|
||
* breakpoint.h (hardware_breakpoint_inserted_here_p): New
|
||
declaration.
|
||
* linux-nat.c (linux_nat_status_is_event): Move higher up in file.
|
||
(linux_resume_one_lwp): Store the thread's PC. Adjust to clear
|
||
stop_reason.
|
||
(check_stopped_by_watchpoint): New function.
|
||
(save_sigtrap): Reimplement.
|
||
(linux_nat_stopped_by_watchpoint): Adjust.
|
||
(linux_nat_lp_status_is_event): Delete.
|
||
(stop_wait_callback): Only call save_sigtrap after storing the
|
||
pending status.
|
||
(status_callback): If the thread had been stopped for a breakpoint
|
||
that has since been removed, discard the event and resume the LWP.
|
||
(count_events_callback, select_event_lwp_callback): Use
|
||
lwp_status_pending_p instead of linux_nat_lp_status_is_event.
|
||
(cancel_breakpoint): Rename to ...
|
||
(check_stopped_by_breakpoint): ... this. Record whether the LWP
|
||
stopped for a software breakpoint or hardware breakpoint.
|
||
(select_event_lwp): Only give preference to the stepping LWP in
|
||
all-stop mode. Adjust comments.
|
||
(stop_and_resume_callback): Remove references to new_pending_p.
|
||
(linux_nat_filter_event): Likewise. Leave exit events of the
|
||
leader thread pending here. Handle signal short circuiting here.
|
||
Only call save_sigtrap after storing the pending waitstatus.
|
||
(linux_nat_wait_1): Remove 'retry' label. Remove references to
|
||
new_pending. Don't handle leaving events the caller is not
|
||
interested in pending here, nor handle signal short-circuiting
|
||
here. Also give equal priority to all LWPs that have had events
|
||
in non-stop mode. If reporting a software breakpoint event,
|
||
unadjust the LWP's PC.
|
||
* linux-nat.h (enum lwp_stop_reason): New.
|
||
(struct lwp_info) <stop_pc>: New field.
|
||
(struct lwp_info) <stopped_by_watchpoint>: Delete field.
|
||
(struct lwp_info) <stop_reason>: New field.
|
||
* x86-linux-nat.c (x86_linux_prepare_to_resume): Adjust.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* linux-nat.c (linux_handle_extended_wait) <PTRACE_EVENT_EXEC>:
|
||
Set the LWP's 'resumed' flag.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* linux-nat.c (linux_resume_one_lwp): New function.
|
||
(resume_lwp): Use lwp_status_pending_p and linux_resume_one_lwp.
|
||
(linux_nat_resume): Use lwp_status_pending_p and
|
||
linux_resume_one_lwp.
|
||
(linux_handle_syscall_trap): Use linux_resume_one_lwp.
|
||
(linux_handle_extended_wait): Use linux_resume_one_lwp.
|
||
(status_callback, running_callback): Use lwp_status_pending_p.
|
||
(lwp_status_pending_p): New function.
|
||
(stop_and_resume_callback): Use lwp_status_pending_p.
|
||
(linux_nat_filter_event): Use linux_resume_one_lwp.
|
||
(linux_nat_wait_1): Always use status_callback to look for an LWP
|
||
with a pending status. Use linux_resume_one_lwp.
|
||
(resume_stopped_resumed_lwps): Use lwp_status_pending_p and
|
||
linux_resume_one_lwp.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* breakpoint.c (bp_location_inserted_here_p): New function,
|
||
factored out from ...
|
||
(breakpoint_inserted_here_p): ... here. Use
|
||
ALL_BP_LOCATIONS_AT_ADDR.
|
||
(software_breakpoint_inserted_here_p): Use
|
||
bp_location_inserted_here_p and ALL_BP_LOCATIONS_AT_ADDR.
|
||
|
||
2014-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
Skip enabling event reporting if the kernel supports
|
||
PTRACE_EVENT_CLONE.
|
||
* linux-thread-db.c: Include "nat/linux-ptrace.h".
|
||
(thread_db_use_events): New function.
|
||
(try_thread_db_load_1): Check thread_db_use_events before enabling
|
||
event reporting.
|
||
(update_thread_state): New function.
|
||
(attach_thread): Use it. Check thread_db_use_events before
|
||
enabling event reporting.
|
||
(thread_db_detach): Check thread_db_use_events before disabling
|
||
event reporting.
|
||
(find_new_threads_callback): Check thread_db_use_events before
|
||
enabling event reporting. Update the thread's state if not using
|
||
libthread_db events.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* linux-nat.c (lin_lwp_attach_lwp): Assert that the lwp id we're
|
||
about to wait for is > 0.
|
||
* linux-thread-db.c (find_new_threads_callback): Ignore thread if
|
||
the kernel thread ID is -1.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* linux-nat.c (attach_proc_task_lwp_callback): New function.
|
||
(linux_nat_attach): Use linux_proc_attach_tgid_threads.
|
||
(wait_lwp, linux_nat_filter_event): If not set yet, set the lwp's
|
||
ptrace option flags.
|
||
* linux-nat.h (struct lwp_info) <must_set_ptrace_flags>: New
|
||
field.
|
||
* nat/linux-procfs.c: Include <dirent.h>.
|
||
(linux_proc_get_int): New parameter "warn". Handle it.
|
||
(linux_proc_get_tgid): Adjust.
|
||
(linux_proc_get_tracerpid): Rename to ...
|
||
(linux_proc_get_tracerpid_nowarn): ... this.
|
||
(linux_proc_pid_get_state): New function, factored out from
|
||
(linux_proc_pid_has_state): ... this. Add new parameter "warn"
|
||
and handle it.
|
||
(linux_proc_pid_is_gone): New function.
|
||
(linux_proc_pid_is_stopped): Adjust.
|
||
(linux_proc_pid_is_zombie_maybe_warn)
|
||
(linux_proc_pid_is_zombie_nowarn): New functions.
|
||
(linux_proc_pid_is_zombie): Use
|
||
linux_proc_pid_is_zombie_maybe_warn.
|
||
(linux_proc_attach_tgid_threads): New function.
|
||
* nat/linux-procfs.h (linux_proc_get_tgid): Update comment.
|
||
(linux_proc_get_tracerpid): Rename to ...
|
||
(linux_proc_get_tracerpid_nowarn): ... this, and update comment.
|
||
(linux_proc_pid_is_gone): New declaration.
|
||
(linux_proc_pid_is_zombie): Update comment.
|
||
(linux_proc_pid_is_zombie_nowarn): New declaration.
|
||
(linux_proc_attach_lwp_func): New typedef.
|
||
(linux_proc_attach_tgid_threads): New declaration.
|
||
* nat/linux-ptrace.c (linux_ptrace_attach_fail_reason): Adjust to
|
||
use nowarn functions.
|
||
(linux_ptrace_attach_fail_reason_string): Move here from
|
||
gdbserver/linux-low.c and rename.
|
||
(ptrace_supports_feature): If the current ptrace options are not
|
||
known yet, check them now, instead of asserting.
|
||
* nat/linux-ptrace.h (linux_ptrace_attach_fail_reason_string):
|
||
Declare.
|
||
|
||
2015-01-09 Pedro Alves <palves@redhat.com>
|
||
|
||
* linux-thread-db.c (thread_db_find_new_threads_silently)
|
||
(try_thread_db_load_1, try_thread_db_load, thread_db_load_search)
|
||
(find_new_threads_once): Print debug output on gdb_stdlog.
|
||
|
||
2015-01-09 Chen Gang <gang.chen.5i5j@gmail.com>
|
||
Pedro Alves <palves@redhat.com>
|
||
|
||
* compile/compile.c: Include "gdb_wait.h".
|
||
(do_rmdir): Check return value, and free 'zap'.
|
||
|
||
2015-01-08 Pedro Alves <palves@redhat.com>
|
||
Yao Qi <yao@codesourcery.com>
|
||
|
||
* dwarf2loc.c (indirect_pieced_value): Don't call
|
||
gdb_sign_extend. Call extract_signed_integer instead.
|
||
* utils.c (gdb_sign_extend): Remove.
|
||
* utils.h (gdb_sign_extend): Remove declaration.
|
||
|
||
2015-01-07 Pierre Muller <muller@sourceware.org>
|
||
|
||
PR symtab/17811
|
||
* stabsread.c (define_symbol): Set language for C++ special symbols.
|
||
|
||
2015-01-07 Patrick Palka <patrick@parcs.ath.cx>
|
||
|
||
* inflow.c (initial_gdb_ttystate): Tweak comment.
|
||
|
||
2015-01-07 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* inflow.c (set_initial_gdb_ttystate): Add empty line after
|
||
comment documenting function.
|
||
|
||
2015-01-07 Patrick Palka <patrick@parcs.ath.cx>
|
||
|
||
* terminal.h (set_initial_gdb_ttystate): Declare.
|
||
* inflow.c (initial_gdb_ttystate): New static variable.
|
||
(set_initial_gdb_ttystate): New setter.
|
||
(child_terminal_init_with_pgrp): Copy initial_gdb_ttystate
|
||
instead of our current terminal state.
|
||
* top.c (gdb_init): Call set_initial_gdb_ttystate.
|
||
|
||
2015-01-07 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* guile/scm-type.c (tyscm_array_1): Add comment.
|
||
* python/py-type.c (typy_array_1): Add comment.
|
||
|
||
2015-01-06 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* guile/scm-type.c (tyscm_array_1): Do not raise out-of-range
|
||
error if N2 is equal to N1 - 1.
|
||
|
||
2015-01-06 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* python/py-type.c (typy_array_1): Do not raise negative-length
|
||
exception if N2 is equal to N1 - 1.
|
||
|
||
2015-01-03 Doug Evans <xdje42@gmail.com>
|
||
|
||
* c-exp.y: Whitespace cleanup.
|
||
(classify_inner_name): Remove extra ;.
|
||
|
||
2015-01-02 Maciej W. Rozycki <macro@codesourcery.com>
|
||
|
||
* mips-tdep.c (mips32_scan_prologue): Keep the extracted stack
|
||
offset signed.
|
||
|
||
2015-01-02 Doug Evans <dje@google.com>
|
||
|
||
* dwarf2read.c (setup_type_unit_groups): Remove outdated comment.
|
||
|
||
2015-01-02 Doug Evans <dje@google.com>
|
||
|
||
* symtab.h (struct symbol): Fix typo in comment.
|
||
|
||
2015-01-01 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
Update year range in copyright notice of all files.
|
||
|
||
2015-01-01 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* top.c (print_gdb_version): Update copyright year to 2015.
|
||
|
||
2015-01-01 Joel Brobecker <brobecker@adacore.com>
|
||
|
||
* config/djgpp/fnchange.lst: Add entry for gdb/ChangeLog-2014.
|
||
|
||
For older changes see ChangeLog-2014.
|
||
|
||
Local Variables:
|
||
mode: change-log
|
||
left-margin: 8
|
||
fill-column: 74
|
||
version-control: never
|
||
coding: utf-8
|
||
End:
|