~ubuntu-support-team/binutils/+git/binutils-gdb:users/palves/ctrl-c
- Git
- lp:~ubuntu-support-team/binutils/+git/binutils-gdb
- users/palves/ctrl-c
- Get this branch:
-
git clone
-b users/palves/ctrl-c
https://git.launchpad.net/~ubuntu-support-team/binutils/+git/binutils-gdb
Branch merges
Related source package recipes
Branch information
- Name:
- users/palves/ctrl-c
Recent commits
- 4e18fe9... by Pedro Alves <email address hidden>
-
Document pseudo-terminal and interrupting changes
This documents changes done in previous patches:
- the fact that on GNU/Linux, GDB creates a pseudo-terminal for the
inferior instead of juggling terminal settings.- That when the inferior and GDB share the terminal, you can't
interrupt some programs with Ctrl-C.- That on GNU/Linux, you may get "Program stopped." instead of
"Program received SIGINT" in response to Ctrl-C.- That run+detach may result in the program dying with SIGHUP.
I was surprised that we do not currently have a node/section
specifically to talk about interrupting programs. Thus I've added a
new "Interrupting" section under the "Stopping and Continuing"
chapter, with some xrefs to other sections.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* NEWS: Document pseudo-terminal, "tty /dev/tty" and Ctrl-C/SIGINT
changes. Document "set/show debug managed-tty".gdb/doc/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* gdb.texinfo (Input/Output): Document that GDB may start a
program associated with a pseudo-terminal. Document "tty
/dev/tty". Document "set/show debug managed-tty".
(Attach): Document what happens on run+detach on systems where GDB
creates a pseudo-terminal for the inferior.
(Stopping and Continuing): Add new Interrupting node.
(Background Execution): Add anchor.
(Features for Debugging MS Windows PE Executables): Add anchor.Change-Id: I267a0f9300c7ac
4d2e7f14a9ba8ea bc1eafcc5a7 - 814fb49... by Pedro Alves <email address hidden>
-
GNU/Linux: Interrupt/Ctrl-C with SIGSTOP instead of SIGINT [PR gdb/9425, PR gdb/14559]
After the "Always put inferiors in their own terminal/session
[gdb/9425, gdb/14559]" change, when a user types "Ctrl-C" while the
inferior is running, GDB is the one who gets the SIGINT, not the
inferior process. GDB then forwards the SIGINT to the inferior with
target_pass_ctrlc.That was necessary but not not sufficient to fix PRs gdb/9425,
gdb/14559, because if a program blocks SIGINT with e.g. sigprocmask,
then if GDB sends it a SIGINT, the signal isn't ever delivered to the
process, so ptrace does not intercept it. You type Ctrl-C, but
nothing happens. Similarly, if a program uses sigwait to wait for
SIGINT, and the program receives a SIGINT, the SIGINT is _not_
intercepted by ptrace, it goes straight to the inferior.Now that the Ctrl-C results in a SIGINT sent to GDB instead of the
inferior, we can make GDB interrupt the program any other way we like.
This patch makes non-stop-capable ports interrupt the program with
stop_all_threads / target_stop (i.e., SIGSTOP) instead of
target_pass_ctrlc (i.e., SIGINT), which always works -- SIGSTOP can't
be blocked/ignored. (In the future GDB may even switch to
PTRACE_INTERRUPT on Linux, though that's a project of its own.)Another advantage here is with multi-target -- currently, because GDB
relies on Ctrl-C stopping one thread, and then stopping all other
threads in reaction to that stop, target_pass_ctrlc tries to find one
inferior with a thread that is running, in any target. If the
selected target for some reason fails to process the Ctrl-C request,
then the Ctrl-C ends up lost. The mechanism implemented in this patch
is different -- we never have to pick a thread, inferior or target --
we're going to stop everything, so we end up in stop_all_threads.For non-stop, the patch preserves the current behavior of only
stopping one thread in reaction to Ctrl-C, so it can still happen that
the thread that GDB selects to stop disappears and the Ctrl-C ends up
being lost. However, because now GDB always sees the SIGINT first, we
can change how Ctrl-C behaves there too. We could even make it
configurable -- for example, it could be reasonable that Ctrl-C simply
drops the CLI back to the prompt, without stopping anything at all.
That might be interesting for "set observer-mode on", at least.This commit has a user-visible behavior change in all-stop mode --
when you interrupt the program with Ctrl-C, instead of:Thread 1 "threads" received signal SIGINT, Interrupt.
You'll get:
Thread 1 "threads" stopped.
Which is what you already got with the "interrupt" command in non-stop
mode.If you really want to pass a SIGINT to the program, you can then issue:
(gdb) signal SIGINT
This commit also adjusts the testsuite to cope with that output
alternative.With this change, the gdb.base/
sigint- sigwait. exp and
gdb.base/sigint- masked- out.exp testcases now pass cleanly on
GNU/Linux, on both native debugging and gdbserver + "maint set
target-non-stop on", so the kfails are adjusted accordingly.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* event-top.c (default_quit_handler) : Mark infrun event-loop
handler with mark_infrun_async_event_ handler_ ctrl_c instead of
passing the Ctrl-C to the target directly with target_pass_ctrlc.
* infcmd.c (interrupt_target_ 1): On non-stop targets, Mark infrun
event-loop handler with
mark_infrun_async_event_ handler_ interrupt_ all instead of using
target_interrupt.
* infrun.c (interrupt_all_requested, switch_ to_stop_ thread)
(sync_interrupt_ all)
(mark_infrun_ async_event_ handler_ interrupt_ all)
(mark_infrun_ async_event_ handler_ ctrl_c) : New.
(infrun_async_inferior_ event_handler) : Handle Ctrl-C/interrupt
requests.
* infrun.h (mark_infrun_async_event_ handler_ interrupt_ all)
(mark_infrun_ async_event_ handler_ ctrl_c) : Declare.
* linux-nat.c (wait_for_signal): Don't handle Ctrl-C here.
(linux_nat_wait_ 1): Handle it here, by marking the infrun event
handler, and returning TARGET_WAITKIND_ IGNORE with the quit flag
still set.
* target.c (maybe_pass_ctrlc): New.
(target_terminal: :inferior, target_ terminal: :restore_ inferior) :
Use it.
(target_pass_ctrlc) : Ass there's no non-stop target pushed. gdb/testsuite/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* gdb.base/bp-cmds- continue- ctrl-c. exp: Expect "stopped" in
alternative to "signal SIGINT".
* gdb.base/interrupt- daemon- attach. exp: Likewise.
* gdb.base/interrupt- daemon. exp: Likewise.
* gdb.base/interrupt- noterm. exp: Likewise.
* gdb.base/interrupt. exp: Likewise.
* gdb.base/random- signal. exp: Likewise.
* gdb.base/range-stepping. exp: Likewise.
* gdb.gdb/selftest. exp: Likewise.
* gdb.mi/new-ui- mi-sync. exp: Likewise.
* gdb.multi/multi-target- interrupt. exp: Likewise.
* gdb.multi/multi-target- no-resumed. exp: Likewise.
* gdb.multi/multi-term- settings. exp: Likewise.
* gdb.server/reconnect- ctrl-c. exp: Likewise.
* gdb.threads/async.exp: Likewise.
* gdb.threads/continue- pending- status. exp: Likewise.
* gdb.threads/leader- exit.exp: Likewise.
* gdb.threads/manythreads. exp: Likewise.
* gdb.threads/pthreads. exp: Likewise.
* gdb.threads/schedlock. exp: Likewise.
* gdb.threads/sigthread. exp: Likewise. * lib/gdb.exp (can_interrupt_
blocked_ sigint) : New.
* gdb.base/sigint- masked- out.exp (test_ctrl_c)
(test_interrupt_ cmd): Use can_interrupt_ blocked_ sigint, and don't
kfail if true.
* gdb.base/sigint- sigwait. exp (test_ctrl_c, test_interrupt_ cmd):
Likewise.Change-Id: I83c1b6a20deea1
f1909156adde1d6 0b8f6f2629b - 86a5798... by Pedro Alves <email address hidden>
-
convert previous_
inferior_ ptid to strong reference to thread_info While working on a patch, I spotted a regression in the
gdb.multi/multi-target- no-resumed. exp.exp testcase. Debugging the
issue, I realized that the problem was related to how I was using
previous_inferior_ ptid to look up the thread the user had last
selected. The problem is that previous_inferior_ ptid alone doesn't
tell you which target that ptid is from, and I was just always using
the current target, which was incorrect. Two different targets may
have threads with the same ptid.I decided to fix this by replacing previous_
inferior_ ptid with a
strong reference to the thread, called previous_thread.A new update_
previous_ thread function is added can be used to updated
previous_thread from inferior_ptid.This must be called in several places that really want to get rid of
previous_thread thread, and reset the thread id counter, otherwise we
get regressions like these:(gdb) info threads -gid
Id GId Target Id Frame
- * 1 1 Thread 2974541.2974541 "tids-gid-reset" main () at src/gdb/testsuite/ gdb.multi/ tids-gid- reset.c: 21
- (gdb) PASS: gdb.multi/tids-gid- reset.exp: single-inferior: after restart: info threads -gid
+ * 1 2 Thread 2958361.2958361 "tids-gid-reset" main () at src/gdb/testsuite/ gdb.multi/ tids-gid- reset.c: 21
+ (gdb) FAIL: gdb.multi/tids-gid- reset.exp: single-inferior: after restart: info threads -gid and:
Core was generated by `build/
gdb/testsuite/ outputs/ gdb.reverse/ sigall- precsave/ si'.
Program terminated with signal SIGTRAP, Trace/breakpoint trap.
#0 gen_ABRT () at src/gdb/testsuite/ gdb.reverse/ sigall- reverse. c:398
398 kill (getpid (), SIGABRT);
+[Current thread is 1 (LWP 2662066)]
Restored records from core file build/gdb/testsuite/ outputs/ gdb.reverse/ sigall- precsave/ sigall. precsave.
#0 gen_ABRT () at src/gdb/testsuite/ gdb.reverse/ sigall- reverse. c:398
398 kill (getpid (), SIGABRT);continue
Continuing.-Program received signal SIGABRT, Aborted.
+Thread 1 received signal SIGABRT, Aborted.
0x00007ffff7dfd55b in kill () at ../sysdeps/ unix/syscall- template. S:78
78 ../sysdeps/unix/syscall- template. S: No such file or directory.
-(gdb) PASS: gdb.reverse/sigall- precsave. exp: sig-test-1: get signal ABRT
+(gdb) FAIL: gdb.reverse/sigall- precsave. exp: sig-test-1: get signal ABRT I.e., GDB was failing to restart the thread counter back to 1, because
the previous_thread thread was being help due to the strong reference.Tested on GNU/Linux native, gdbserver and gdbserver + "maint set
target-non-stop on".gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* infcmd.c (kill_command, detach_command, disconnect_
command) :
Call update_previous_ thread.
* infrun.c (previous_inferior_ ptid): Delete.
(previous_thread): New.
(update_previous_ thread) : New.
(proceed, init_wait_for_inferior) : Call update_ previous_ thread.
(normal_stop): Adjust to compare previous_thread and
inferior_thread. Call update_previous_ thread.
* infrun.h (update_previous_ thread) : Declare.
* target.c (target_pre_inferior, target_preopen): Call
update_previous_ thread. Change-Id: I4f06dd81f00848
bb7d6d26a94ff09 1e2a4e646d9 - de89924... by Pedro Alves <email address hidden>
-
exists_
non_stop_ target: Avoid flushing frames A following patch adds an exists_
non_stop_ target call in the
target_terminal routines, and that surprisingly caused a weird
regression / GDB crash:$ make check RUNTESTFLAGS=
"--target_ board=native- extended- gdbserver" TESTS=" gdb.base/ signest. exp"
...
configuring for gdbserver local testing (extended-remote)
Using src/gdb/testsuite/ config/ extended- gdbserver. exp as tool-and- target- specific interface file.
Running src/gdb/testsuite/ gdb.base/ signest. exp ...
ERROR: GDB process no longer existsDebugging the core, we see infinite recursion:
(top-gdb) bt 20
#0 0x0000561d6a1bfeff in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#1 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#2 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#3 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#4 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#5 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#6 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#7 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#8 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#9 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#10 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#11 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#12 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#13 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#14 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#15 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#16 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#17 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#18 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#19 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
(More stack frames follow...)(top-gdb) bt -30
#157054 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#157055 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#157056 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#157057 0x0000561d6a1bfeb8 in get_frame_arch (this_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2939
#157058 0x0000561d6a1b989f in frame_unwind_find_by_ frame (this_frame= 0x561d6b19f9c0, this_cache= 0x561d6b19f9d8) at src/gdb/ frame-unwind. c:174
#157059 0x0000561d6a1bff04 in frame_unwind_arch (next_frame=0x561d6b19f9c0) at src/gdb/ frame.c: 2950
#157060 0x0000561d6a1bbc65 in frame_unwind_pc (this_frame=0x561d6b19f9c0) at src/gdb/frame.c:970
#157061 0x0000561d6a1bf54c in get_frame_pc (frame=0x561d6b19fa90) at src/gdb/ frame.c: 2625
#157062 0x0000561d6a1bf63e in get_frame_address_ in_block (this_frame= 0x561d6b19fa90) at src/gdb/ frame.c: 2655
#157063 0x0000561d6a0cae7f in dwarf2_frame_cache (this_frame=0x561d6b19fa90, this_cache= 0x561d6b19faa8) at src/gdb/ dwarf2/ frame.c: 1010
#157064 0x0000561d6a0cb928 in dwarf2_frame_this_ id (this_frame= 0x561d6b19fa90, this_cache= 0x561d6b19faa8, this_id= 0x561d6b19faf0) at src/gdb/ dwarf2/ frame.c: 1227
#157065 0x0000561d6a1baf72 in compute_frame_id (fi=0x561d6b19fa90) at src/gdb/frame.c:588
#157066 0x0000561d6a1bb16e in get_frame_id (fi=0x561d6b19fa90) at src/gdb/frame.c:636
#157067 0x0000561d6a1bb224 in get_stack_frame_id (next_frame=0x561d6b19fa90) at src/gdb/frame.c:650
#157068 0x0000561d6a26ecd0 in insert_hp_step_ resume_ breakpoint_ at_frame (return_ frame=0x561d6b1 9fa90) at src/gdb/ infrun. c:7809
#157069 0x0000561d6a26b88a in handle_signal_stop (ecs=0x7ffc67022830) at src/gdb/ infrun. c:6428
#157070 0x0000561d6a269d81 in handle_inferior_ event (ecs=0x7ffc6702 2830) at src/gdb/ infrun. c:5741
#157071 0x0000561d6a265bd0 in fetch_inferior_event () at src/gdb/ infrun. c:4120
#157072 0x0000561d6a244c24 in inferior_event_handler (event_ type=INF_ REG_EVENT) at src/gdb/ inf-loop. c:41
#157073 0x0000561d6a435cc4 in remote_async_serial_ handler (scb=0x561d6b4a 8990, context= 0x561d6b4a4c48) at src/gdb/ remote. c:14403
#157074 0x0000561d6a460bc5 in run_async_handler_ and_reschedule (scb=0x561d6b4a 8990) at src/gdb/ ser-base. c:138
#157075 0x0000561d6a460cae in fd_event (error=0, context=0x561d6b4a8990) at src/gdb/ ser-base. c:189
#157076 0x0000561d6a76a191 in handle_file_event (file_ptr=0x561d6b233ae0, ready_mask=1) at src/gdbsupport/ event-loop. cc:575
#157077 0x0000561d6a76a743 in gdb_wait_for_event (block=1) at src/gdbsupport/event-loop. cc:701
#157078 0x0000561d6a7694ee in gdb_do_one_event () at src/gdbsupport/event-loop. cc:237
#157079 0x0000561d6a2df16b in start_event_loop () at src/gdb/main.c:421
#157080 0x0000561d6a2df2b6 in captured_command_ loop () at src/gdb/main.c:481
#157081 0x0000561d6a2e0d16 in captured_main (data=0x7ffc67022bd0) at src/gdb/main.c:1353
#157082 0x0000561d6a2e0da8 in gdb_main (args=0x7ffc67022bd0) at src/gdb/main.c:1370
#157083 0x0000561d69eb3d82 in main (argc=13, argv=0x7ffc67022cf8, envp=0x7ffc6702 2d68) at src/gdb/gdb.c:33 This was caused by exists_
non_stop_ target flushing the frame cache via
scoped_restore_ current_ thread/ switch_ to_thread, while we're in the
middle of unwinding.Fix this by making exists_
non_stop_ target only switch the inferior,
like done in target_pass_ctrlc.The annota1.exp change is necessary because we'd get a regression
otherwise:@@ -238,8 +238,6 @@ Continuing.
\032\
032breakpoints- invalid -\032\
032frames- invalid
-
\032\032breakpoint 3 Breakpoint 3,
@@ -276,7 +274,7 @@ printf.c
\032\032pre- prompt
(gdb)
\032\032prompt
-PASS: gdb.base/annota1. exp: continue to printf
+FAIL: gdb.base/annota1. exp: continue to printf ... because this patch avoids flushing the frame cache that lead to
that missing frames-invalid. We still need to match frames-invalid
because against gdbserver + "maint set target non-stop on", some other
code path flushes the frame cache resulting in the annotation being
emitted anyway.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* target.c (exists_
non_stop_ target) : Use
scoped_restore_ current_ inferior and set_current_ inferior instead
of scoped_restore_ current_ thread / switch_ to_inferior_ no_thread. Change-Id: I8402483ee755e6
4e54d8b7c4a67c1 77557f569bd - d9bda17... by Pedro Alves <email address hidden>
-
Always put inferiors in their own terminal/session [gdb/9425, gdb/14559]
Currently, on GNU/Linux, it is not possible to interrupt with Ctrl-C
programs that block or ignore SIGINT, with e.g., sigprocmask or
signal(SIGINT, SIG_IGN). You type Ctrl-C, but nothing happens.
Similarly, if a program uses sigwait to wait for SIGINT, and the
program receives a SIGINT, the SIGINT is _not_ intercepted by ptrace,
it goes straight to the inferior. These problems have been known for
years, and recorded in gdb/9425, gdb/14559.This is a consequence of how GDB implements interrupting programs with
Ctrl-C -- when GDB spawns a new process, it makes the process use the
same terminal as GDB, and then makes the process's process group be
the foreground process group in GDB's terminal. This means that when
the process is running in the foreground, after e.g. "continue", when
the user types Ctrl-C, the kernel sends a SIGINT to the foreground
process group, which is the inferior. GDB then intercepts the SIGINT
via ptrace, the same way it intercepts any other signal, stops all the
other threads of the inferior if in all-stop, and presents the
"Program received SIGINT" stop to the user.This patch paves the way to address gdb/9425, gdb/14559, by turning
Ctrl-C handling around such that the SIGINT always reaches GDB first,
not the inferior. That is done by making GDB put inferiors in their
own terminal/session created by GDB. I.e., GDB creates a
pseudo-terminal master/slave pair, makes the inferior run with the
slave as its terminal, and pumps output/input on the master end.
Because the inferior is run with its own session/terminal, GDB is free
to remain as the foreground process in its own terminal, which means
that the Ctrl-C SIGINT always reaches GDB first, instead of reaching
the inferior first, and then GDB reacting to the ptrace-intercepted
SIGINT. Because GDB gets the SIGINT first, GDB is then free to
handle it by interrupting the program any way it sees fit. A
following patch will then make GDB interrupt the program with SIGSTOP
instead of SIGINT, which always works even if the inferior
blocks/ignores SIGINT -- SIGSTOP can't be ignored. (In the future GDB
may even switch to PTRACE_INTERRUPT, though that's a project of its
own.)Having the inferior in its own terminal also means that GDB is in
control of when inferior output is flushed to the screen. When
debugging with the CLI, this means that inferior output is now never
interpersed with GDB's output in an unreadable fashion. This will
also allow fixing the problem of inferior output really messing up the
screen in the TUI, forcing users to Ctrl-L to refresh the screen.
This patch does not address the TUI part, but it shouldn't be too hard
-- I wrote a quick&dirty prototype patch doing that a few years back,
so I know it works.Implementation wise, here's what is happening:
- when GDB spawns an inferior, unless the user asked otherwise with
"tty /dev/tty", GDB creates a pty pair, and makes the slave end the
inferior's terminal. Note that starting an inferior on a given
terminal already exists, given the "tty" command. GDB records the
master and slave ends of the pty.- GDB registers that new terminal's master end on the event loop.
When the master is written to, it means the inferior has written
some output on its terminal. The event loop wakes up and GDB
flushes the inferior output to its own terminal / to the screen.- When target_terminal state is switched to "inferior", with
target_tarminal: :inferiors( ), GDB registers the stdin file
descriptor on the event loop with a callback that forwards input
typed on GDB's terminal to the inferior's tty.- Similarly, when GDB receives a SIGWINCH signal, meaning GDB's
terminal was resized, GDB resizes the inferior's terminal too.- GDB puts the inferior in its own session, and there's a "session
leader" process between GDB and the inferior. The latter is
because session leaders have special properties, one of which is,
if they exit, all progresses in the foreground process group in the
session get a SIGHUP. If the spawned inferior was the session
leader itself, if you were debugging an inferior that forks and
follow to the child, if the parent (the session leader) exits, then
the child would get a SIGHUP. Forking twice when launching an
inferior, and making the first child be the session leader, and the
second child the inferior avoids that problem.- When the inferior exits or is killed, GDB sends a SIGHUP to the
session leader, waits for the leader to exit and then destroys the
terminal. The session leader's SIGHUP handler makes the session
leader pgrp be the foreground process group and then exits. This
sequence is important comparing to just closing the terminal and
letting the session leader terminate due to the SIGHUP the kernel
sends, because when the session leader exits, all processes in the
foreground process group get a SIGHUP, meaning that if the detached
process was still in the foreground, it would get a SIGHUP, and
likely die.- The gdb.multi/
multi-term- settings. exp was adjusted to test for
shared and not-shared terminal/session. Without the change, we get
failures:FAIL: gdb.multi/
multi-term- settings. exp: inf1_how=run: inf2_how=run: continue (expected SIGTTOU)
FAIL: gdb.multi/multi-term- settings. exp: inf1_how=run: inf2_how=run: stop with control-c (Quit) Tested on GNU/Linux native, gdbserver and gdbserver + "maint target
set-non-stop on". Also build-tested tested on mingw32-w64, Solaris
11, and OpenBSD.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* fork-child.c (child_has_managed_ tty_hook) : New.
* inf-ptrace.c (inf_ptrace_me): If we created a managed tty, raise
SIGSTOP.
(inf_ptrace_handle_ session_ leader_ fork): New.
(inf_ptrace_target: :create_ inferior) : Pass it down as
handle_session_ leader_ fork callback.
* inf-ptrace.h (inf_ptrace_target) <handle_session_ leader_ fork>:
New virtual method.
* inferior.h (child_terminal_ on_sigwinch) : Declare.
* inflow.c: Include "gdbsupport/event-loop. h",
"gdbsupport/refcounted- object. h", "gdbsupport/ gdb_wait. h",
"gdbsupport/managed- tty.h".
(USES_FORK_CHILD): Define, and wrap fork-child.c-related code with
it.
(struct run_terminal_info): New.
(struct terminal_info) <run_terminal>: Now a run_terminal_info.
<process_group>: Default to -1.
<save_from_tty>: New method.
(sigint_ours): Update comments.
(inferior_thisrun_ terminal_ pty_fd) : New.
(input_fd_redirected) : New.
(sharing_input_terminal) : Adjust.
(gdb_tcgetattr, gdb_tcsetattr, make_raw, class scoped_raw_termios)
(child_terminal_ flush_from_ to, child_terminal_ flush_stdout)
(inferior_stdout_ event_handler, inferior_ stdin_event_ handler) : New.
(child_terminal_ inferior) : Handle inferiors with gdb-managed ttys.
(child_terminal_ save_inferior) : Handle inferiors with gdb-managed
ttys. Use save_from_tty.
(child_terminal_ ours_1) : Handle inferiors with gdb-managed ttys.
(terminal_info::~ terminal_ info): Use delete instead of xfree.
(child_terminal_ on_sigwinc) : New.
(inflow_inferior_ exit): Release terminal created by GDB.
(copy_terminal_ info): Assert there's no run_terminal yet in TO
yet. Incref run_terminal after copying.
(child_terminal_ info): Handle inferiors with gdb-managed ttys.
(new_tty_prefork): Allocate pseudo-terminal.
(created_managed_ tty): New.
(new_tty): Remove __GO32__ and _WIN32 #ifdefs, not needed given
USES_FORK_CHILD.
(new_tty_postfork) : Handle inferiors with gdb-managed ttys.
(show_debug_managed_ tty): New.
(_initialize_inflow) : Register "set/show debug managed-tty".
* linux-nat.c (waitpid_sigstop, waitpid_fork)
(linux_nat_target: :handle_ session_ leader_ fork): New.
* linux-nat.h (linux_nat_target) <handle_session_ leader_ fork>:
Declare override.
* nat/fork-inferior. c: Include
"gdbsupport/scoped_ ignore_ sigttou. h", "gdbsupport/ managed- tty.h",
<sys/types.h> and <sys/wait.h>.
(session_leader_ hup): New.
(fork_inferior): Add handle_session_ leader_ fork parameter. If the
inferior has a gdb-managed tty, don't use vfork, and fork twice,
with the first fork becoming the session leader. Call
handle_session_ leader_ fork.
* nat/fork-inferior.h (fork_inferior): Add
handle_session_ leader_ fork parameter and update comment.
(child_has_managed_ tty_hook) : Declare.
* terminal.h (created_managed_ tty, child_gdb_ owns_session) :
Declare.
* tui/tui-win.c: Include "inferior.h".
(tui_async_resize_ screen) : Call child_terminal_ on_sigwinch. gdbsupport/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* Makefile.am (libgdbsupport_a_SOURCES) : Add managed-tty.cc.
* Makefile.in: Regenerate.
* managed-tty.cc: New.
* managed-tty.h: New.gdbserver/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* fork-child.cc (child_has_managed_ tty_hook) : New. gdb/testsuite/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>PR gdb/9425
PR gdb/14559
* gdb.multi/multi-term- settings. exp (create_inferior): Document
"run-session", "run-share" and "run-tty" instead of "run" and
"tty". Adjust to handle "run-session" vs "run-share".
(coretest): Adjust to handle "run-session" vs "run-share".
(how_modes): Use "run-session", "run-share" and "run-tty" instead
of "run" and "tty".Change-Id: I2569e189294044
891e68a66401b38 1e4b999b19c - 9f84272... by Pedro Alves <email address hidden>
-
Move scoped_
ignore_ sigttou to gdbsupport/ A following patch will want to use scoped_
ignore_ sigttou in code
shared between GDB and GDBserver. Move it under gdbsupport/.Note that despite what inflow.h/inflow.c's first line says, inflow.c
is no longer about ptrace, it is about terminal management. Some
other files were unnecessarily including inflow.h, I guess a leftover
from the days when inflow.c really was about ptrace. Those inclusions
are simply dropped.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* Makefile.in (HFILES_NO_SRCDIR): Remove inflow.h.
* inf-ptrace.c, inflow.c, procfs.c: Don't include "inflow.h".
* inflow.h: Delete, moved to gdbsupport/ under a different name.
* ser-unix.c: Don't include "inflow.h". Include
"gdbsupport/scoped_ ignore_ sigttou. h". gdbsupport/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* scoped_
ignore_ sigttou. h: New file, moved from gdb/ and renamed. Change-Id: Ie390abf42c3a78
bec6d282ad2a63e dd3e623559a - 5cd9932... by Pedro Alves <email address hidden>
-
target_
terminal: :ours_for_ output before printing signal received A following patch will make GDB put spawned inferiors in their own
terminal/session (on GNU/Linux). In that case, GDB is in control of
when is the inferior's output flushed to the screen. A sync point is
when target_terminal state goes from inferior -> ours/ours_for_output. The gdb.multi/
multi-term- settings. exp testcase exposed a bug where an
inferior output flush is missing, resulting in this regression:Good:
(gdb) PASS: gdb.multi/
multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: info inferiors
continue
Continuing.
pid=1275538, count=0
pid=1276069, count=0Thread 1.1 "multi-term-sett" received signal SIGTTOU, Stopped (tty output).
[Switching to process 1275538]
0x00007ffff7ecda14 in __tcsetattr (fd=0, optional_actions=0, termios_p=0x7fffffffd45 0) at ../sysdeps/ unix/sysv/ linux/tcsetattr .c:83
83 ../sysdeps/unix/sysv/ linux/tcsetattr .c: No such file or directory.
(gdb) PASS: gdb.multi/multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: continue (expected SIGTTOU)
Quit
(gdb) PASS: gdb.multi/multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: stop with control-c (Quit) Bad:
(gdb) PASS: gdb.multi/
multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: info inferiors
continue
Continuing.
pid=1287638, count=0Thread 1.1 "multi-term-sett" received signal SIGTTOU, Stopped (tty output).
pid=1287663, count=0 <<<<<< HERE
[Switching to process 1287638]
0x00007ffff7ecda14 in __tcsetattr (fd=0, optional_actions=0, termios_p=0x7fffffffd45 0) at ../sysdeps/ unix/sysv/ linux/tcsetattr .c:83
83 ../sysdeps/unix/sysv/ linux/tcsetattr .c: No such file or directory.
(gdb) FAIL: gdb.multi/multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: continue
Quit
(gdb) PASS: gdb.multi/multi-term- settings. exp: inf1_how=run-share: inf2_how= run-session: stop with control-c (Quit) Notice the "<<<<<< HERE" line in the "Bad" output above -- that is
inferior output being printed on the screen _after_ GDB says the
thread stopped... That's obviously bogus, the output was printed by
the inferior before it was stopped.The fix is to claim back the terminal for output before printing the
"signal received SIGTTOU" message.gdb/ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* infrun.c (normal_stop): Call target_
terminal: :ours_for_ output
before calling signal_received observers.Change-Id: Iea106c33b4c585
562fc3579ca85d4 3481fa214f0 - 6579312... by Pedro Alves <email address hidden>
-
gdb.mi/
mi-logging. exp, don't send input to GDB while the inferior is running The gdb.mi/
mi-logging. exp testcase sends a sequence of execution
commands to the GDB terminal while the inferior is running, like this:send_gdb "1002-exec-step\n"
send_gdb "1003-exec-next\n"expecting that GDB will consume the "1003-exec-next" intput after the
inferior stops for the 1002-exec-step.That's a flawed assumption in general, because the inferior itself
could consume the "1003-exec-next" input while it is stepping.When GDB puts the inferior in its own terminal, while the inferior is
running, GDB marshals input from its terminal to the inferior's
terminal. The result is that input typed while the inferior is
running never goes to GDB, and so the test fails.The previous patch addressed issues like this by making the inferior
and GDB share the same terminal for tests that really wanted to test
some aspect of a shared terminal. For gdb.mi/mi-logging. exp though,
there's really no reason to send input while the program is running,
so the fix here is to stop it from doing so.While debugging the testcase, I ran into the fact that it reuses the
same log file for more than one [open] sequence, overwriting previous
runs. The testcase also deletes the log files at the very end, which
makes it impossible to inspect the logs after a failure run. The
patch addresses those issues as well.gdb/testsuite/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* gdb.mi/
mi-logging. exp: Do not reuse log files for different
runs. Delete logs at the start of the testcase, not at the
end.
(wait_open, gdb_test_file): New procedures. Use them.Change-Id: Ife215a82391a02
0041fd05478bd8d bee6e04d607 - 9d5edd4... by Pedro Alves <email address hidden>
-
Make inferior/GDB share terminal in tests that exercise GDB/inferior reading same input
Some testcases exercise some aspect that only makes sense when GDB and
the inferior are sharing the same terminal, meaning GDB and the
inferior are reading from the same input file.This commit makes sure that continues to be tested even after GDB
changed to put inferiors in their own session/terminal by default, by
issuing "tty /dev/tty". The tests would fail otherwise.gdb/testsuite/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* gdb.base/
annota- input-while- running. exp: Issue "tty /dev/tty"
before starting program.
* gdb.base/continue- all-already- running. exp: Likewise.
* gdb.base/infcall- input.exp: Likewise. Change-Id: Ia5f9061bf28a5e
780194aa75b37b6 058de0614ee - 8db79a5... by Pedro Alves <email address hidden>
-
Make inferior/GDB share terminal in tests expecting output after detach
A following patch will make GDB put spawned inferiors in their own
terminal/session. A consequence of that is that if you do "run", and
then "detach", GDB closes the terminal, so expecting inferior output
after detach no longer works, the inferior is alive, but its output
goes nowhere.There's only one testcase that expects output out of an inferior after
detach. Tweak it to output to GDB's terminal instead.gdb/testsuite/
ChangeLog:
yyyy-mm-dd Pedro Alves <email address hidden>* gdb.threads/
process- dies-while- detaching. exp: Issue "tty
/dev/tty" before starting program.Change-Id: Ic62bca17829576
3fb9c47657ee459 fe715f7865e