From patchwork Sat Oct 20 15:38:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Marchi X-Patchwork-Id: 29818 Received: (qmail 4504 invoked by alias); 20 Oct 2018 15:38:41 -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 4482 invoked by uid 89); 20 Oct 2018 15:38:40 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=am, a.m, sk:follow_, UD:a.m X-HELO: smtp.polymtl.ca Received: from smtp.polymtl.ca (HELO smtp.polymtl.ca) (132.207.4.11) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 20 Oct 2018 15:38:38 +0000 Received: from simark.ca (simark.ca [158.69.221.121]) (authenticated bits=0) by smtp.polymtl.ca (8.14.7/8.14.7) with ESMTP id w9KFcTYj001457 (version=TLSv1/SSLv3 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sat, 20 Oct 2018 11:38:34 -0400 Received: from [10.0.0.11] (unknown [192.222.164.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by simark.ca (Postfix) with ESMTPSA id 148CC1E4C2; Sat, 20 Oct 2018 11:38:28 -0400 (EDT) Subject: Re: [PATCH 3/3] Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368) From: Simon Marchi To: Pedro Alves , gdb-patches@sourceware.org References: <20181016033835.17594-1-simon.marchi@polymtl.ca> <20181016033835.17594-3-simon.marchi@polymtl.ca> <37bde004-853a-3ccc-3777-03cc43b36147@redhat.com> Message-ID: <5375d6a4-8b4d-af3a-2b37-f0b88363d5d3@polymtl.ca> Date: Sat, 20 Oct 2018 11:38:27 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes On 2018-10-20 11:13 a.m., Simon Marchi wrote: > On 2018-10-17 1:04 p.m., Pedro Alves wrote: >> On 10/16/2018 04:38 AM, Simon Marchi wrote: >>> Here's a summary of PR 23368: >>> >>> #include >>> int main (void) >>> { >>> char *exec_args[] = { "/bin/ls", NULL }; >>> execve (exec_args[0], exec_args, NULL); >>> } >>> >>> $ gdb -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run >>> ... >>> [1] + 13146 suspended (tty output) gdb -q -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run >>> $ >>> >>> Here's what happens: when the inferior execs with "follow-exec-mode >>> new", we first "mourn" it before creating the new one. This ends up >>> calling inflow_inferior_exit, which sets the per-inferior terminal state >>> to "is_ours": >>> >>> inf->terminal_state = target_terminal_state::is_ours; >>> >>> At this point, the inferior's terminal_state is is_ours, while the >>> "reality", tracked by gdb_tty_state, is is_inferior (GDB doesn't own the >>> terminal). >>> >>> Later, we continue processing the exec inferior event and decide we want >>> to stop (because of the "catch exec") and call target_terminal::ours to >>> make sure we own the terminal. However, we don't actually go to the >>> target backend to change the settings, because the core thinks that no >>> inferior owns the terminal (inf->terminal_state is >>> target_terminal_state::is_ours, as checked in >>> target_terminal_is_ours_kind, for both inferiors). >> ^^^^^^^^^^^^^^^^^^ >> >> I think the "for both inferiors" part is what's dubious here. >> >> The process lives on in the new inferior, but we lost its >> terminal settings! Seems to me that they should be migrated >> from the old inferior to the new one. And then the problem >> sorts itself out, because then the new inferior will have >> target_terminal_state::is_inferior state. > > Yeah that makes sense. This crossed my mind when I look at the issue, > but for some reason I didn't went that route. But now that you say it, > it appears obvious that this should be the fix. > > I just tried copying the inferior::terminal_state value from the old > inferior to the new inferior, and it fixes the problem. But > actually, we should also be transferring all of the struct terminal_info > associated to the inferior, is that right? This would be the updated patch (testing on the buildbot at the moment). From c54c1dc3f124aef65c8a1daf042ded2b6b4a8a46 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Sat, 20 Oct 2018 10:57:33 -0400 Subject: [PATCH] Avoid GDB SIGTTOU on catch exec + set follow-exec-mode new (PR 23368) Here's a summary of PR 23368: #include int main (void) { char *exec_args[] = { "/bin/ls", NULL }; execve (exec_args[0], exec_args, NULL); } $ gdb -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run ... [1] + 13146 suspended (tty output) gdb -q -nx t -ex "catch exec" -ex "set follow-exec-mode new" -ex run $ Here's what happens: when the inferior execs with "follow-exec-mode new", we first "mourn" it before creating the new one. This ends up calling inflow_inferior_exit, which sets the per-inferior terminal state to "is_ours": inf->terminal_state = target_terminal_state::is_ours; At this point, the inferior's terminal_state is is_ours, while the "reality", tracked by gdb_tty_state, is is_inferior (GDB doesn't own the terminal). Later, we continue processing the exec inferior event and decide we want to stop (because of the "catch exec") and call target_terminal::ours to make sure we own the terminal. However, we don't actually go to the target backend to change the settings, because the core thinks that no inferior owns the terminal (inf->terminal_state is target_terminal_state::is_ours, as checked in target_terminal_is_ours_kind, for both inferiors). When something in readline tries to mess with the terminal settings, it generates a SIGTTOU. This patch fixes this by tranferring the state of the terminal from the old inferior to the new inferior. gdb/ChangeLog: * infrun.c (follow_exec): In the follow_exec_mode_new case, transfer terminal state from old new new inferior. --- gdb/infrun.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gdb/infrun.c b/gdb/infrun.c index 72e249617670..85a5200ddf4b 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1189,12 +1189,13 @@ follow_exec (ptid_t ptid, char *exec_file_target) /* The user wants to keep the old inferior and program spaces around. Create a new fresh one, and switch to it. */ - /* Do exit processing for the original inferior before adding - the new inferior so we don't have two active inferiors with - the same ptid, which can confuse find_inferior_ptid. */ + /* Do exit processing for the original inferior before setting the new + inferior's pid. Having two inferiors with the same pid would confuse + find_inferior_p(t)id. */ + inf = add_inferior_with_spaces (); + copy_terminal_info (inf, current_inferior ()); exit_inferior_silent (current_inferior ()); - inf = add_inferior_with_spaces (); inf->pid = pid; target_follow_exec (inf, exec_file_target);