From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id ccBYBTPgyWARCAAAWB0awg (envelope-from ) for ; Wed, 16 Jun 2021 07:27:47 -0400 Received: by simark.ca (Postfix, from userid 112) id 06ECB1F163; Wed, 16 Jun 2021 07:27:47 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=MAILING_LIST_MULTI, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 88C061E939 for ; Wed, 16 Jun 2021 07:27:45 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 7C006396E859 for ; Wed, 16 Jun 2021 11:27:44 +0000 (GMT) Received: from mail-wr1-f46.google.com (mail-wr1-f46.google.com [209.85.221.46]) by sourceware.org (Postfix) with ESMTPS id 73848384803E for ; Wed, 16 Jun 2021 11:27:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 73848384803E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=palves.net Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-wr1-f46.google.com with SMTP id o3so2270619wri.8 for ; Wed, 16 Jun 2021 04:27:32 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:from:to:cc:references:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=j6kA1ZAu7tRM3cEhCqfowytU6nYdbyE5uHMyIzHSHyI=; b=pSlf0HMiRXwhaa1ZEJEgYK05vYqsmBKCPVzl8Y+3jifT0itpP2uz1FlNX9MWHjb2Hr jHmUiZISge+MnBlzeJv8o2f4I+eXfavEieaunc4IZqbuSfzrKNEQhS5JIZxuwelIamJC YpNewhW7xM0L1J4dG3QNdvI3ZcuHyDJK44fKxX3e+o10s3AA4S7yIViphz4g4cOO8cwN rxvPx1bofzS7JvCjLzJxwlY25xqAylePRp82HR3J15YbvOMBpMb6Fu2ICTeVe+hG2Lzk FWDlsTzroFSXhqHjZ1Yb6X8v5eS3qx0f9qp63d31ckvXHcYFoCGpQ93JxsVR3I5hMk20 gscg== X-Gm-Message-State: AOAM531wGCpEzcjaCf6sP5LoXKv0Ugbcmvt2kKepevZUdGCt1uh76pVQ OkouSZYEqEZy+eFkETgXi5k58suFzgIJIA== X-Google-Smtp-Source: ABdhPJytVP4AwB/JEgdjo6dbEX7U7ed2wh/qiMKDaqbFpHEBpilysO/gI1ZDAU8lXF3EgvO/zBbwHQ== X-Received: by 2002:a5d:65cc:: with SMTP id e12mr2574631wrw.354.1623842850113; Wed, 16 Jun 2021 04:27:30 -0700 (PDT) Received: from ?IPv6:2001:8a0:f932:6a00:6b6e:c7b6:c5a7:aac3? ([2001:8a0:f932:6a00:6b6e:c7b6:c5a7:aac3]) by smtp.gmail.com with ESMTPSA id l20sm1565925wmq.3.2021.06.16.04.27.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 16 Jun 2021 04:27:29 -0700 (PDT) Subject: Re: [PATCH v2 00/16] Interrupting programs that block/ignore SIGINT From: Pedro Alves To: Eli Zaretskii References: <20210614212410.1612666-1-pedro@palves.net> <83sg1j488r.fsf@gnu.org> Message-ID: Date: Wed, 16 Jun 2021 12:27:28 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.11.0 MIME-Version: 1.0 In-Reply-To: <83sg1j488r.fsf@gnu.org> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: gdb-patches@sourceware.org Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" On 2021-06-15 1:34 p.m., Eli Zaretskii wrote: >> From: Pedro Alves >> Date: Mon, 14 Jun 2021 22:23:54 +0100 >> >> 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. > > For the reasons I explained in my other message, can we please talk > about "stopping a program" instead of "interrupting"? Both in the log > message (and the discussion) and in the documentation, please. At > least for me, the use of "interrupt" was confusing. > >> This series address the problem 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. > > Is this "pumping" really-truly 100% transparent to the program being > debugged? I understand how a program that uses stdio will simply read > the same stuff that was "pumped" from GDB's terminal, but what about > other kinds of input and settings? > > For example, some text-mode programs change the settings of the > terminal via termios -- will those settings be reflected in the GDB's > terminal when the debuggee reads or writes from its terminal? Or what > about support for terminfo functions -- will the commands be passed > back and forth between the terminals and the user will see the effects > he/she expects? Some terminal emulators support advanced features > like cut/paste -- will that also work with this pumping? And if the > program changes the character that causes SIGINT (Emacs does that when > it runs on a text-mode terminal), will that change the interrupt > character for GDB as well? Debugging curses programs works fine, because we "pump" all input/output between the terminals, escape sequences and all. E.g., I use the TUI frequently, and debugging gdb with itself and enabling the TUI in the inferior gdb works fine. No other pumping is done, only input/output. When the new terminal is created, it inherits the terminal settings of the GDB terminal, but otherwise, the inferior's terminal settings are not reflected in GDB's terminal settings. I mean, if the program changes \n -> \r\n translation in the inferior, that changes the inferior's terminal, and what ends up output to the pseudo-terminal slave end. When GDB flushes that into its own terminal, GDB puts its own terminal in raw mode, so that exactly whatever characters/bytes the inferior wanted to send to the screen, they end up in GDB's terminal. Similarly for the input direction. Cut/paste works fine for me, but I'm not sure I'm trying what you are suggesting. E.g., I debug a GDB that is running in TUI mode, and then I can use the mouse to select text (shift click drag) and then paste it back (shift middle click). This is all implemented in the terminal emulator, the application has no idea about it, it's just text grabbed from the screen, and then input back into the application, as if you typed it. Changing the interrupt character does not work. If I debug emacs in text-mode, and then press ctrl-c, it drops you back into GDB, like: Thread 1 "emacs" stopped. 0x00007ffff5197246 in __pselect (nfds=9, readfds=0x7fffffffc8a0, writefds=0x7fffffffc920, exceptfds=0x0, timeout=, sigmask=) at ../sysdeps/unix/sysv/linux/pselect.c:48 | 48 ../sysdeps/unix/sysv/linux/pselect.c: No such file or directory. (gdb) If I press "ctrl-g", I then get "Program stopped by SIGINT": Thread 1 "emacs" received signal SIGINT, Interrupt. 0x00007ffff5197246 in __pselect (nfds=9, readfds=0x7fffffffc8a0, writefds=0x7fffffffc920, exceptfds=0x0, timeout=, sigmask=) at ../sysdeps/unix/sysv/linux/pselect.c:48 | 48 in ../sysdeps/unix/sysv/linux/pselect.c (gdb) I see this as a feature and it goes back to the "supervisor" idea discussed in the other thread. To change the "supervisor" interrupt key, you have to change the interrupt key in the supervisor's terminal, with e.g., "$ stty intr ^G". or even "(gdb) shell stty intr ^G". Not unlike if you had attached to emacs instead of spawned it. I guess the emacs's emacs-gdb.gdb file could run that stty command, so it is run automatically when debugging emacs. The altered intr key will remain in effect after gdb exits, though. (I can reproduce it with current GDB.) I guess GDB could grow a built-in command for that to avoid it. But, shouldn't GDB restore terminal settings on exit? That's easy to do, GDB already saves the initial terminal settings when it starts up, to pass them down to inferiors when their started. See patch at the bottom. That does restore the intr key. > >> The series 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. > > And if the user then types "continue", will SIGINT be delivered to the > program, or will the Ctrl-C keystroke be "swallowed" by GDB? Already answered elsewhere, but yes, it will be swallowed, just like today by default. > >> 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. > > I guess this will be done on the screen line level? Because if a > program uses terminfo or curses to write to different parts of the > screen, the outputs of the program and GDB will mix anyhow, just not > on the same screen line, right? > Yeah, all I meant is that the inferior and GDB won't be concurrently writing to the screen at the same time, E.g., if you continue the program in the background (continue&), and the program prints to the screen, if you do e.g. "help all", the inferior output won't be flushed until all the help text is printed. I should probably just drop that sentence, it's not that important. Pedro Alves >From c98f0866f70b473399193f45186cd7fbdb43e3aa Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 16 Jun 2021 12:12:52 +0100 Subject: [PATCH] restore terminal settings on exit Change-Id: I7afb648d6a17ee7588b1963518a5a79b20ebb8c9 --- gdb/inflow.c | 11 ++++++++++- gdb/terminal.h | 6 +++++- gdb/top.c | 4 +++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/gdb/inflow.c b/gdb/inflow.c index 35a51b26fb5..f100bd58dfc 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -207,7 +207,7 @@ static bool input_fd_redirected = false; /* See terminal.h. */ void -set_initial_gdb_ttystate (void) +save_initial_gdb_ttystate (void) { /* Note we can't do any of this in _initialize_inflow because at that point stdin_serial has not been created yet. */ @@ -227,6 +227,15 @@ set_initial_gdb_ttystate (void) } } +/* See terminal.h. */ + +void +restore_initial_gdb_ttystate () +{ + if (initial_gdb_ttystate != NULL) + serial_set_tty_state (stdin_serial, initial_gdb_ttystate); +} + /* Does GDB have a terminal (on stdin)? */ static int diff --git a/gdb/terminal.h b/gdb/terminal.h index f8ef29bc2a9..8661a8fc519 100644 --- a/gdb/terminal.h +++ b/gdb/terminal.h @@ -44,6 +44,10 @@ extern void gdb_save_tty_state (void); /* Take a snapshot of our initial tty state before readline/ncurses have had a chance to alter it. */ -extern void set_initial_gdb_ttystate (void); +extern void save_initial_gdb_ttystate (void); + +/* Restore the terminal settings back to what they were at GDB + startup. */ +extern void restore_initial_gdb_ttystate (); #endif /* !defined (TERMINAL_H) */ diff --git a/gdb/top.c b/gdb/top.c index 6e0f43d2fd9..ee6b45774a4 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1841,6 +1841,8 @@ quit_force (int *exit_arg, int from_tty) exception_print (gdb_stderr, ex); } + restore_initial_gdb_ttystate (); + exit (exit_code); } @@ -2401,7 +2403,7 @@ gdb_init () /* Take a snapshot of our tty state before readline/ncurses have had a chance to alter it. */ - set_initial_gdb_ttystate (); + save_initial_gdb_ttystate (); async_init_signals (); -- 2.26.2