From patchwork Tue May 30 10:53:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 70308 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B4F1D3855889 for ; Tue, 30 May 2023 10:53:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B4F1D3855889 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1685444035; bh=DgmVPvnsVr//kqMwJZwnzw/P49bUZRfBEglHIat7PPc=; h=To:Cc:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=gemjf/weJaL9CPWq3gLqh95jSu1gPo+fO8wzKWqVQELjabPWPtMpwJkeMRzVtHyin 35qebfWYIMl5DcGGVXA6fvgSu6UJMoMj9qQB8M3nQ3QIvvhSjqAMj6KwMEDxzcZz2B qnokFaS2hWVn9ZLFTKFofdYWVRc7a9ae1nbIWHXM= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by sourceware.org (Postfix) with ESMTPS id 3708D3858C5E for ; Tue, 30 May 2023 10:53:27 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3708D3858C5E Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 66A791F8D9; Tue, 30 May 2023 10:53:26 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 5018413478; Tue, 30 May 2023 10:53:26 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id ODN9EqbVdWTNZgAAMHmgww (envelope-from ); Tue, 30 May 2023 10:53:26 +0000 To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH 2/3] [gdb] Add observable terminal_owner_changed Date: Tue, 30 May 2023 12:53:23 +0200 Message-Id: <20230530105324.23089-3-tdevries@suse.de> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230530105324.23089-1-tdevries@suse.de> References: <20230530105324.23089-1-tdevries@suse.de> MIME-Version: 1.0 X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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: , X-Patchwork-Original-From: Tom de Vries via Gdb-patches From: Tom de Vries Reply-To: Tom de Vries Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Add a new observable, gdb::observers::terminal_owner_changed. Its observers are notified when gdb_tty_state changes. On each change, they are notified twice: - once with the old gdb_tty_state, and active == false, and - once with the new gdb_tty_state, and active == true. No functional changes. Tested on x86_64-linux. --- gdb/inflow.c | 176 ++++++++++++++++++++++++++--------------------- gdb/observable.c | 1 + gdb/observable.h | 5 ++ 3 files changed, 103 insertions(+), 79 deletions(-) diff --git a/gdb/inflow.c b/gdb/inflow.c index 767cfd02c48..9c82306be62 100644 --- a/gdb/inflow.c +++ b/gdb/inflow.c @@ -311,67 +311,76 @@ child_terminal_inferior (struct target_ops *self) inferior *inf = current_inferior (); terminal_info *tinfo = get_inflow_inferior_data (inf); - if (gdb_has_a_terminal () - && tinfo->ttystate != NULL - && sharing_input_terminal (inf)) - { - int result; + if (!(gdb_has_a_terminal () + && tinfo->ttystate != NULL + && sharing_input_terminal (inf))) + return; - /* Ignore SIGTTOU since it will happen when we try to set the - terminal's state (if gdb_tty_state is currently - ours_for_output). */ - scoped_ignore_sigttou ignore_sigttou; + /* Note that the old state will no longer be active. */ + gdb::observers::terminal_owner_changed.notify (gdb_tty_state, false); + + /* Scope containing scoped_ignore_sigtto. */ + { + int result; + + /* Ignore SIGTTOU since it will happen when we try to set the + terminal's state (if gdb_tty_state is currently + ours_for_output). */ + scoped_ignore_sigttou ignore_sigttou; #ifdef F_GETFL - result = fcntl (0, F_SETFL, tinfo->tflags); - OOPSY ("fcntl F_SETFL"); + result = fcntl (0, F_SETFL, tinfo->tflags); + OOPSY ("fcntl F_SETFL"); #endif - result = serial_set_tty_state (stdin_serial, tinfo->ttystate); - OOPSY ("setting tty state"); + result = serial_set_tty_state (stdin_serial, tinfo->ttystate); + OOPSY ("setting tty state"); - if (!job_control) - { - sigint_ours = install_sigint_handler (SIG_IGN); + if (!job_control) + { + sigint_ours = install_sigint_handler (SIG_IGN); #ifdef SIGQUIT - sigquit_ours = signal (SIGQUIT, SIG_IGN); + sigquit_ours = signal (SIGQUIT, SIG_IGN); #endif - } + } - if (job_control) - { + if (job_control) + { #ifdef HAVE_TERMIOS_H - /* If we can't tell the inferior's actual process group, - then restore whatever was the foreground pgrp the last - time the inferior was running. See also comments - describing terminal_state::process_group. */ + /* If we can't tell the inferior's actual process group, + then restore whatever was the foreground pgrp the last + time the inferior was running. See also comments + describing terminal_state::process_group. */ #ifdef HAVE_GETPGID - result = tcsetpgrp (0, getpgid (inf->pid)); + result = tcsetpgrp (0, getpgid (inf->pid)); #else - result = tcsetpgrp (0, tinfo->process_group); + result = tcsetpgrp (0, tinfo->process_group); #endif - if (result == -1) - { + if (result == -1) + { #if 0 - /* This fails if either GDB has no controlling terminal, - e.g., running under 'setsid(1)', or if the inferior - is not attached to GDB's controlling terminal. E.g., - if it called setsid to create a new session or used - the TIOCNOTTY ioctl, or simply if we've attached to a - process running on another terminal and we couldn't - tell whether it was sharing GDB's terminal (and so - assumed yes). */ - gdb_printf - (gdb_stderr, - "[tcsetpgrp failed in child_terminal_inferior: %s]\n", - safe_strerror (errno)); + /* This fails if either GDB has no controlling terminal, + e.g., running under 'setsid(1)', or if the inferior + is not attached to GDB's controlling terminal. E.g., + if it called setsid to create a new session or used + the TIOCNOTTY ioctl, or simply if we've attached to a + process running on another terminal and we couldn't + tell whether it was sharing GDB's terminal (and so + assumed yes). */ + gdb_printf + (gdb_stderr, + "[tcsetpgrp failed in child_terminal_inferior: %s]\n", + safe_strerror (errno)); #endif - } + } #endif - } + } - gdb_tty_state = target_terminal_state::is_inferior; - } + gdb_tty_state = target_terminal_state::is_inferior; + } + + /* Note that the new state is active. */ + gdb::observers::terminal_owner_changed.notify (gdb_tty_state, true); } /* Put some of our terminal settings into effect, @@ -447,55 +456,64 @@ child_terminal_ours_1 (target_terminal_state desired_state) if (!gdb_has_a_terminal ()) return; - if (gdb_tty_state != desired_state) - { - int result ATTRIBUTE_UNUSED; + if (gdb_tty_state == desired_state) + return; - /* Ignore SIGTTOU since it will happen when we try to set the - terminal's pgrp. */ - scoped_ignore_sigttou ignore_sigttou; + /* Note that the old state will no longer be active. */ + gdb::observers::terminal_owner_changed.notify (gdb_tty_state, false); - /* Set tty state to our_ttystate. */ - serial_set_tty_state (stdin_serial, our_terminal_info.ttystate); + /* Scope containing scoped_ignore_sigtto. */ + { + int result ATTRIBUTE_UNUSED; - /* If we only want output, then leave the inferior's pgrp in the - foreground, so that Ctrl-C/Ctrl-Z reach the inferior - directly. */ - if (job_control && desired_state == target_terminal_state::is_ours) - { + /* Ignore SIGTTOU since it will happen when we try to set the + terminal's pgrp. */ + scoped_ignore_sigttou ignore_sigttou; + + /* Set tty state to our_ttystate. */ + serial_set_tty_state (stdin_serial, our_terminal_info.ttystate); + + /* If we only want output, then leave the inferior's pgrp in the + foreground, so that Ctrl-C/Ctrl-Z reach the inferior + directly. */ + if (job_control && desired_state == target_terminal_state::is_ours) + { #ifdef HAVE_TERMIOS_H - result = tcsetpgrp (0, our_terminal_info.process_group); + result = tcsetpgrp (0, our_terminal_info.process_group); #if 0 - /* This fails on Ultrix with EINVAL if you run the testsuite - in the background with nohup, and then log out. GDB never - used to check for an error here, so perhaps there are other - such situations as well. */ - if (result == -1) - gdb_printf (gdb_stderr, - "[tcsetpgrp failed in child_terminal_ours: %s]\n", - safe_strerror (errno)); + /* This fails on Ultrix with EINVAL if you run the testsuite + in the background with nohup, and then log out. GDB never + used to check for an error here, so perhaps there are other + such situations as well. */ + if (result == -1) + gdb_printf (gdb_stderr, + "[tcsetpgrp failed in child_terminal_ours: %s]\n", + safe_strerror (errno)); #endif #endif /* termios */ - } + } - if (!job_control && desired_state == target_terminal_state::is_ours) - { - if (sigint_ours.has_value ()) - install_sigint_handler (*sigint_ours); - sigint_ours.reset (); + if (!job_control && desired_state == target_terminal_state::is_ours) + { + if (sigint_ours.has_value ()) + install_sigint_handler (*sigint_ours); + sigint_ours.reset (); #ifdef SIGQUIT - if (sigquit_ours.has_value ()) - signal (SIGQUIT, *sigquit_ours); - sigquit_ours.reset (); + if (sigquit_ours.has_value ()) + signal (SIGQUIT, *sigquit_ours); + sigquit_ours.reset (); #endif - } + } #ifdef F_GETFL - result = fcntl (0, F_SETFL, our_terminal_info.tflags); + result = fcntl (0, F_SETFL, our_terminal_info.tflags); #endif - gdb_tty_state = desired_state; - } + gdb_tty_state = desired_state; + } + + /* Note that the new state is active. */ + gdb::observers::terminal_owner_changed.notify (gdb_tty_state, true); } /* Interrupt the inferior. Implementation of target_interrupt for diff --git a/gdb/observable.c b/gdb/observable.c index 82563e3fab4..2ae9f325899 100644 --- a/gdb/observable.c +++ b/gdb/observable.c @@ -82,6 +82,7 @@ DEFINE_OBSERVABLE (gdb_exiting); DEFINE_OBSERVABLE (connection_removed); DEFINE_OBSERVABLE (target_pre_wait); DEFINE_OBSERVABLE (target_post_wait); +DEFINE_OBSERVABLE (terminal_owner_changed); } /* namespace observers */ } /* namespace gdb */ diff --git a/gdb/observable.h b/gdb/observable.h index e4e6f021f1a..9a4144a13ca 100644 --- a/gdb/observable.h +++ b/gdb/observable.h @@ -22,6 +22,7 @@ #include "gdbsupport/observable.h" #include "target/waitstatus.h" +#include "target/target.h" struct bpstat; struct so_list; @@ -276,6 +277,10 @@ extern observable target_pre_wait; /* About to leave target_wait (). */ extern observable target_post_wait; +/* When the terminal owner changes. */ +extern observable + terminal_owner_changed; + } /* namespace observers */ } /* namespace gdb */