Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Partha Satapathy <partha.satapathy@oracle.com>
To: Guinevere Larsen <blarsen@redhat.com>,
	gdb-patches@sourceware.org, bert.barbe@oracle.com,
	rajesh.sivaramasubramaniom@oracle.com
Subject: Re: [External] : Re: [PATCH] gdb : Signal to pstack/gdb kills the attached process.
Date: Thu, 2 Nov 2023 23:54:25 +0530	[thread overview]
Message-ID: <baf3ff58-f9f1-4248-a682-219b4e78b8da@oracle.com> (raw)
In-Reply-To: <bd8a7eef-88c6-30a6-a12a-5edd95d6cd74@redhat.com>

On 10/25/2023 9:24 PM, Guinevere Larsen wrote:
> Hi!
> 
> Thanks for working on this issue, and sorry about the delay in getting 
> this reviewed. For future reference, we (at least I) tend to try and go 
> for patches with many pings, so it is better to ping existing patches 
> than re-sending them :)

I some how missed this mail, hence a delay in reply.
I sorry for this and unfortunately have made the mistake once again.
Hope the extra threads can be deleted and I will keep my discussion 
bound to this thread.

> 
> I'm not very knowledgeable on how GDB does signal handling, so I'm going 
> to review this patch at face value. I hope someone who does know how 
> this part works gets a look at this soon!
> 
> On 16/10/2023 11:28, Partha Satapathy wrote:
>> Problem :
>> While gdb attaching a target, If ctrl-c pressed in the midst of the 
>> process attach,  the sigint is passed to the debugged process. This 
>> triggers exit of the debugged.
>>
>> Let’s take the example of pstack,  which dumps the stack of all 
>> threads in a process. In some cases printing of stack can take 
>> significant time and ctrl-c is pressed to abort pstack/gdb 
>> application. This in turn kills the debugged process, which can be 
>> critical for the system. In this case the intention of “ctrl+c” to 
>> kill pstack/gdb, but not the target application.
>>
>> Reproduction:
>>
>> The debugged application generally attached to process by:
>> gdb -p <<pid>>
>> or gdb /proc/<<pid>>/exe pid
>> pstack uses the latter  method to attach the debugged to gdb. If the 
>> application is large or process of reading symbols is slow, gives a 
>> good window to press the ctrl+c during attach. Spawning "gdb" under 
>> "strace -k" makes gdb a lot slower and gives a larger window to easily 
>> press the
>> ctrl+c at the precise period i.e. during the attach of the debugged
>> process. The above strace hack will enhance rate of reproduction of 
>> the issue. Testcase:
>>
>> With GDB 13.1
>> ps aux | grep abrtd
>> root     2195168   /usr/sbin/abrtd -d -s
>>
>> #strace -k -o log gdb -p 2195168
>> Attaching to process 2195168
>> [New LWP 2195177]
>> [New LWP 2195179]
>> ^C[Thread debugging using libthread_db enabled]
>> <<<<   Note the ctrl+c is pressed after attach is initiated and it’s
>> still reading the symbols from library >>>> Using host libthread_db 
>> library "/lib64/libthread_db.so.1".
>> 0x00007fe3ed6d70d1 in poll () from /lib64/libc.so.6
>> (gdb) q
>> A debugging session is active.
>>           Inferior 1 [process 2195168] will be detached Quit anyway? 
>> (y or n) y Detaching from program: /usr/sbin/abrtd, process 2195168
>>
>> # ps aux | grep 2195168
>> <<<< Process exited >>>>
>>
>> Description:
>>
>> We are installing a signal handler in gdb that marks the Ctrl-c/sigint 
>> received by gdb. GDB passes this sigint to the debugged at some 
>> definite points during the window of process attach. The process of 
>> attaching debugged  involves steps like PTRACE_ATTACH , reading 
>> symbols, getting the stop signal from the debugged and get ready with 
>> GDB prompt. Note:
>> one of the example of this is sigint passing is:
>> "     - installs a SIGINT handler that forwards SIGINT to the inferior.
>>          Otherwise a Ctrl-C pressed just while waiting for the initial
>>          stop would end up as a spurious Quit.
>> "
>>
>> There are few other places where sigint is passed to the debugged 
>> during attach of process to gdb. As the debugger and debugged are not 
>> fully attached during this period, the sigint takes its default action 
>> and terminates the process.
>>
>> Solution:
>>
>> While gdb attaches process, the target is not the current session 
>> leader. Hence, until attach is complete and GDB prompt is availed, the 
>> sigint should not be passed to the debugged. A similar approach is 
>> taken for "gdb) run &". In target_terminal::inferior()
>>     /* A background resume (``run&'') should leave GDB in control of the
>>        terminal.  */
>>     if (ui->prompt_state != PROMPT_BLOCKED)
>>       return;
>>
>> The passing of signal is skipped if the process ran in background. 
>> With this approach we can skip passing the sigint if the process is 
>> attached to gdb and process attach is not complete.
>> Here is the proposed solution:
>>
>>
>>
>> Fix :
>>
>> While gdb attaching a target, If ctrl-c/sigint pressed in the midst of 
>> the process attach, the sigint is passed to the debugged process.
>> This triggers exit of the debugged.
>>
>> This issue is evident while getting the process stack with ./gdb 
>> --quiet -nx  -ex 'set width 0' -ex 'set height 0'
>> -ex 'set pagination no' -ex 'set confirm off'
>> -ex 'thread apply all bt' -ex quit /proc/<PID>/exe <PID> and press the 
>> ctrl+c while attach.
>>
>> The above method is also used in pstack application which is a wrapper 
>> over gdb to print the process stack. A Ctrl+C intended to kill gdb or 
>> pstack, but kills the debugged even if it is attached and not spawned 
>> by gdb.
> 
> This is a very good description of the error you've encountered, but 
> given the repetition on this "fix:" part, I'm wondering, what is meant 
> to be the commit message? Is it just these last few lines, or is it the 
> whole thing? If it is just this last bit, I think it would benefit from 
> some more explanation of the solution. If it is the whole message, I 
> think you can reduce a bit the repetition.
> 
> Also, at many points you say "debugged process" and "target". In 
> GDB-land we call that the "inferior". Target has a very specific meaning 
> in the context of GDB (roughly the CPU you're running, and some extra 
> bits here and there).
> 
> I also have a few comments on the specific changes, that are inlined.
> 
>> ---
>>   gdb/inferior.h | 3 +++
>>   gdb/target.c   | 4 ++++
>>   gdb/top.c      | 2 ++
>>   3 files changed, 9 insertions(+)
>>
>> diff --git a/gdb/inferior.h b/gdb/inferior.h index 
>> 4d001b0ad50e..b7048d10bbe4 100644
>> --- a/gdb/inferior.h
>> +++ b/gdb/inferior.h
>> @@ -557,6 +557,9 @@ class inferior : public refcounted_object,
>>     /* True if this child process was attached rather than forked.  */
>>     bool attach_flag = false;
>>
>> +  /* True if target process synced and gdb ui is out of block. */ bool
> 
> This comment is oddly worded. Based on the change to gdb/top.c, I think 
> you could reword it like this:
> 
> /* True if inferior has been fully synced and the prompt is no longer 
> blocked.  */
> 
>> + sync_flag = false;
> Typo here, the variable's type should be on this line.
>> +
>>     /* If this inferior is a vfork child, then this is the pointer to
>>        its vfork parent, if GDB is still attached to it.  */
>>     inferior *vfork_parent = NULL;
>> diff --git a/gdb/target.c b/gdb/target.c index 
>> d5bfd7d0849b..f7c115497451 100644
>> --- a/gdb/target.c
>> +++ b/gdb/target.c
>> @@ -3826,6 +3826,10 @@ target_pass_ctrlc (void)
>>                   through the target_stack.  */
>>                scoped_restore_current_inferior restore_inferior;
>>                set_current_inferior (inf);
>> +             if ((current_inferior()->attach_flag) &&
> 
> A couple of style issues here: when the indentation would have 8 spaces, 
> you should use a tab instead;
> 
> There should be a space between the function name and the parameters;
> And when you need to cut a logical expression in half, the operator 
> should be at the start of a new line.
> 
>> + !(current_inferior()->sync_flag)) {
> In this case, since it is just one line, there is no need to have the 
> curly braces. However, when they are needed, they should be on the 
> following line, and 2 spaces further in indentation.
>> + return;
>> +             }
>>                current_inferior ()->top_target ()->pass_ctrlc ();
>>                return;
>>              }
>> diff --git a/gdb/top.c b/gdb/top.c
>> index 621aa6883233..26cc6caac0e5 100644
>> --- a/gdb/top.c
>> +++ b/gdb/top.c
>> @@ -542,6 +542,8 @@ wait_sync_command_done (void)
>>     while (gdb_do_one_event () >= 0)
>>       if (ui->prompt_state != PROMPT_BLOCKED)
>>         break;
>> +
>> +  current_inferior()->sync_flag = true;
> 
> I'm not very knowledgeable on this part of GDB, so take this with a 
> grain of salt, but I wonder if this is the best place to put this.
> 
> Since you only set this flag as false when first creating the inferior 
> structure, I don't see why it should be re-set every time we're waiting 
> for a command to be done. You could set the sync flag to false every 
> command, but that feels like overkill. I feel like there should be some 
> a mechanism in GDB already that knows if we're the session leader or 
> not, and thus handles things correctly, but I don't know what it is.
> 
> Another possibility, based on the exact problem you had, is to put this 
> at the end of either symbol expansions, or the reasons they are being 
> expanded in the first place (which I suspect is something like trying to 
> identify the language or  name of the main function).
> 

wait_sync_command_done() is not frequently called with command execution.
strace -k -o log ./gdb -p <<pid>>
(gdb) ls
Undefined command: "ls".  Try "help".
(gdb) !ls
(gdb) disassemble main

confirmed the function wait_sync_command_done() is not part of this 
trace. wait_sync_command_done() is called from run_inferior_call()
and serve as inferior startup and wait for it to stop.

/* Subroutine of call_function_by_hand to simplify it.
    Start up the inferior and wait for it to stop.
    Return the exception if there's an error, or an exception with
    reason >= 0 if there's no error.

    This is done inside a TRY_CATCH so the caller needn't worry about
    thrown errors.  The caller should rethrow if there's an error.  */

static struct gdb_exception
run_inferior_call (std::unique_ptr<call_thread_fsm> sm,
                    struct thread_info *call_thread, CORE_ADDR real_pc)
{

       /* Inferior function calls are always synchronous, even if the
          target supports asynchronous execution.  */
       wait_sync_command_done ();

So wait_sync_command_done called once per inferior at startup.


Hi Guinevere,

Thanks for the review and sorry for the delay in reply.
Please find comments inline.

I will send the V2 incorporating rest of the comment.

Thanks
Partha

  reply	other threads:[~2023-11-02 18:25 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-16  9:28 Partha Satapathy
2023-10-25 15:54 ` Guinevere Larsen
2023-11-02 18:24   ` Partha Satapathy [this message]
2023-11-02 18:27     ` [External] : Re: [PATCH v2] " Partha Satapathy
2023-11-06 13:38       ` Guinevere Larsen
2023-11-17 14:48         ` [External] : Re: [PATCH v3] " Partha Satapathy
2023-12-03  5:51           ` Partha Satapathy
2023-12-05 13:13           ` Guinevere Larsen
2024-01-10 15:59             ` Partha Satapathy
2024-01-24 15:19               ` Partha Satapathy
2024-02-19  5:10                 ` Partha Satapathy
2024-03-05  8:47                   ` Guinevere Larsen
2024-03-07  8:41                     ` Partha Satapathy
2024-03-07  9:58                     ` [External] : Re: [PATCH v4] " Partha Satapathy
2024-03-26  9:59                       ` Partha Satapathy
2024-03-26  9:59                       ` Partha Satapathy
2024-04-16 10:14                         ` Partha Satapathy

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=baf3ff58-f9f1-4248-a682-219b4e78b8da@oracle.com \
    --to=partha.satapathy@oracle.com \
    --cc=bert.barbe@oracle.com \
    --cc=blarsen@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=rajesh.sivaramasubramaniom@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox