From patchwork Wed Jan 7 14:12:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 4545 Received: (qmail 17835 invoked by alias); 7 Jan 2015 14:13:06 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 17821 invoked by uid 89); 7 Jan 2015 14:13:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 X-HELO: mail-qc0-f172.google.com Received: from mail-qc0-f172.google.com (HELO mail-qc0-f172.google.com) (209.85.216.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 07 Jan 2015 14:13:02 +0000 Received: by mail-qc0-f172.google.com with SMTP id m20so920619qcx.17 for ; Wed, 07 Jan 2015 06:13:00 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:date:to:cc:subject:in-reply-to:message-id :references:user-agent:mime-version:content-type; bh=6p547pV7+8Qli/hiHc4A0IO+ACgQUNTWvGH9qvBAHXo=; b=HIA/IQjtFuEuJwKaxNOZI9qOeSwmYuefjY8TX5I0t++cB1+/FOlPPguuXwQwVASfOf 9Bj9f1yFl7dSD431ng6IeKz1vB6hJvHZPDTJe5quqcLHhUNfh+adFaxFRa0s5VDMECAF RYuot8sJ0LjIBORtVnngKMIeUq/V+q3MBmrXgxWDjoKdd+kZkN7NzFeJKbh2kq+NcAoQ 3CMBMUWMJguq+nebU/vFYQatXpLi8jqKtQcqairshpwWFRDuSypKxmI6Imz2HAaaZNzd R8hTtD6B2E/QMke2bzBbpBQLPNhvVP68f+CPhb7+2nmVNeYTT1Axpt8pw9BPLWHoH+lE vdHw== X-Gm-Message-State: ALoCoQmP4ByrTj0+26LcbkrKlI/Yzc7IbmQbFT4EykZv5+iCJNiJcMAzUP5kotVXkpADGwwiJJ3i X-Received: by 10.140.43.52 with SMTP id d49mr4701367qga.94.1420639980413; Wed, 07 Jan 2015 06:13:00 -0800 (PST) Received: from [192.168.1.130] (ool-4353ac94.dyn.optonline.net. [67.83.172.148]) by mx.google.com with ESMTPSA id r2sm1441804qah.1.2015.01.07.06.12.59 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 07 Jan 2015 06:12:59 -0800 (PST) From: Patrick Palka X-Google-Original-From: Patrick Palka Date: Wed, 7 Jan 2015 09:12:53 -0500 (EST) To: Pedro Alves cc: gdb-patches@sourceware.org Subject: Re: [PATCH] [RFC] Don't propagate our current terminal state to the inferior In-Reply-To: <54AD3716.7070209@redhat.com> Message-ID: References: <1416688748-20448-1-git-send-email-patrick@parcs.ath.cx> <54AD3716.7070209@redhat.com> User-Agent: Alpine 2.11 (DEB 23 2013-08-11) MIME-Version: 1.0 On Wed, 7 Jan 2015, Pedro Alves wrote: > On 11/22/2014 08:39 PM, Patrick Palka wrote: >> Currently when we start an inferior we have the inferior inherit our >> terminal state. Under TUI, our terminal is highly modified by ncurses >> and readline. So when starting an inferior under TUI, the inferior will >> have a highly modified terminal state which will interfere with standard >> I/O. For example, >> >> $ gdb gdb >> (gdb) break main >> (gdb) run >> (gdb) print puts ("a\nb") >> a >> b >> $1 = 4 >> (gdb) [enter TUI mode] >> (gdb) run >> (gdb) [exit TUI mode] >> (gdb) print puts ("a\nb") >> a >> b >> $2 = 4 >> (gdb) print puts ("a\r\nb\r") >> a >> b >> $3 = 6 >> >> As you can see, when we start the inferior under the regular interface, >> puts() prints the text properly. But when we start the inferior under >> TUI, puts() does not print the text properly. This is because when we >> start the inferior under TUI it inherits our current terminal state >> which has been modified by ncurses to, among other things, require an >> explicit \r\n to print a new line. As a result the inferior performs >> standard I/O in an unexpected way. >> >> Because of this discrepancy, it doesn't seem like a good idea to have >> the inferior inherit our _current_ terminal state for it may have been >> modified by readline and/or ncurses. Instead, we should have the >> inferior inherit a pristine snapshot of our terminal state taken before >> readline or ncurses have had a chance to alter it. This enables the >> inferior to run in a more accurate way, more closely mimicking its >> behavior had the program run standalone. And it fixes the above >> mentioned issue. >> >> I wonder, does this change make sense? What do others think? > > Thanks. This makes sense to me. > >> >> +/* The initial tty state given to each new inferior. It is a snapshot of our >> + own tty state taken during initialization of GDB. */ >> +static serial_ttystate initial_inferior_ttystate; >> + >> static struct terminal_info *get_inflow_inferior_data (struct inferior *); >> >> #ifdef PROCESS_GROUP_TYPE >> @@ -156,6 +160,13 @@ show_interactive_mode (struct ui_file *file, int from_tty, >> fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value); >> } >> >> +/* Set the initial tty state that is to be inherited by new inferiors. */ >> +void >> +set_initial_inferior_ttystate (void) >> +{ >> + initial_inferior_ttystate = serial_get_tty_state (stdin_serial); >> +} > > "initial inferior" reminded me of the initial inferior that > GDB always creates. E.g., in main.c: > > /* Now that gdb_init has created the initial inferior, we're in > position to set args for that inferior. */ > > > Could you rename the function and the variable? Like: > > set_initial_gdb_ttystate (void) > { > initial_gdb_ttystate = serial_get_tty_state (stdin_serial); > } > > ... > > /* Snapshot of our own tty state taken during initialization > of GDB. This is used as tty state given to each new inferior. */ > static serial_ttystate initial_gdb_ttystate; > > > > Calling the variable that way calls it for what it holds, not > for how it is used, which is friendlier to reuse in > other situations. > > This would be OK with me with that change. > > Thanks, > Pedro Alves > > Thanks Pedro. I have changed the names of the new function and variable and committed the patch. Please let me know if I have messed up the commit procedure. Final patch: -- >8 -- Subject: [PATCH] Don't propagate our current terminal state to the inferior Currently when we start an inferior we have the inferior inherit our terminal state. Under TUI, our terminal is highly modified by ncurses and readline. So when starting an inferior under TUI, the inferior will have a highly modified terminal state which will interfere with standard I/O. For example, $ gdb gdb (gdb) break main (gdb) run (gdb) print puts ("a\nb") a b $1 = 4 (gdb) [enter TUI mode] (gdb) run (gdb) [exit TUI mode] (gdb) print puts ("a\nb") a b $2 = 4 (gdb) print puts ("a\r\nb\r") a b $3 = 6 As you can see, when we start the inferior under the regular interface, puts() prints the text properly. But when we start the inferior under TUI, puts() does not print the text properly. This is because when we start the inferior under TUI it inherits our current terminal state which has been modified by ncurses to, among other things, require an explicit \r\n to print a new line. As a result the inferior performs standard I/O in an unexpected way. Because of this discrepancy, it doesn't seem like a good idea to have the inferior inherit our _current_ terminal state for it may have been modified by readline and/or ncurses. Instead, we should have the inferior inherit a pristine snapshot of our terminal state taken before readline or ncurses have had a chance to alter it. This enables the inferior to run in a more accurate way, more closely mimicking the program's behavior had it run standalone. And it fixes the above mentioned issue. Tested on x86_64-unknown-linux-gnu. gdb/ChangeLog: * 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. --- gdb/ChangeLog | 9 +++++++++ gdb/inflow.c | 13 ++++++++++++- gdb/terminal.h | 2 ++ gdb/top.c | 4 ++++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0b63d34..6477dc1 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2015-01-07 Patrick Palka + + * 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 * guile/scm-type.c (tyscm_array_1): Add comment. diff --git a/gdb/inflow.c b/gdb/inflow.c index 8947e63..3c121a3 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -79,6 +79,10 @@ struct terminal_info unimportant. */ static struct terminal_info our_terminal_info; +/* The initial tty state given to each new inferior. It is a snapshot of our + own tty state taken during initialization of GDB. */ +static serial_ttystate initial_gdb_ttystate; + static struct terminal_info *get_inflow_inferior_data (struct inferior *); #ifdef PROCESS_GROUP_TYPE @@ -156,6 +160,13 @@ show_interactive_mode (struct ui_file *file, int from_tty, fprintf_filtered (file, "Debugger's interactive mode is %s.\n", value); } +/* Set the initial tty state that is to be inherited by new inferiors. */ +void +set_initial_gdb_ttystate (void) +{ + initial_gdb_ttystate = serial_get_tty_state (stdin_serial); +} + /* Does GDB have a terminal (on stdin)? */ int gdb_has_a_terminal (void) @@ -227,7 +238,7 @@ child_terminal_init_with_pgrp (int pgrp) { xfree (tinfo->ttystate); tinfo->ttystate = serial_copy_tty_state (stdin_serial, - our_terminal_info.ttystate); + initial_gdb_ttystate); /* Make sure that next time we call terminal_inferior (which will be before the program runs, as it needs to be), we install the new diff --git a/gdb/terminal.h b/gdb/terminal.h index ae25c98..17acde2 100644 --- a/gdb/terminal.h +++ b/gdb/terminal.h @@ -103,6 +103,8 @@ extern int gdb_has_a_terminal (void); extern void gdb_save_tty_state (void); +extern void set_initial_gdb_ttystate (void); + /* Set the process group of the caller to its own pid, or do nothing if we lack job control. */ extern int gdb_setpgid (void); diff --git a/gdb/top.c b/gdb/top.c index 524a92b..b85ea1a 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -1890,6 +1890,10 @@ gdb_init (char *argv0) initialize_stdin_serial (); + /* Take a snapshot of our tty state before readline/ncurses have had a chance + to alter it. */ + set_initial_gdb_ttystate (); + async_init_signals (); /* We need a default language for parsing expressions, so simple