This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: RFA/gdbserver: GDB internal-error debugging threaded program with breakpoint and forks
- From: Pedro Alves <palves at redhat dot com>
- To: Joel Brobecker <brobecker at adacore dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Tue, 28 Jun 2016 20:40:09 +0100
- Subject: Re: RFA/gdbserver: GDB internal-error debugging threaded program with breakpoint and forks
- Authentication-results: sourceware.org; auth=none
- References: <20160512171650 dot GC26324 at adacore dot com> <5734C06C dot 8040008 at codesourcery dot com> <20160623225935 dot GC3295 at adacore dot com> <20160624181152 dot GD3295 at adacore dot com> <31daa4d2-359d-db9a-e9c8-d7bfbb327570 at redhat dot com> <20160624223616 dot GE3295 at adacore dot com> <9170a848-2c63-0e42-a478-23753c1f495b at redhat dot com> <20160627223200 dot GF3295 at adacore dot com>
On 06/27/2016 11:32 PM, Joel Brobecker wrote:
>>>> I haven't gone through this with fine-tooth comb yet, but,
>>>> will we still have the same problem if _two_ threads (or inferiors...)
>>>> fork at the "same" time, and we end up reporting one fork, while
>>>> leaving the another one pending?
>>>
>>> At the moment, I do not think so, because we seem to just process
>>> the fork even without requesting an update of the thread list.
>>
>> "catch fork" would make us stop though.
>
> :-(. Most likely. I had the weekend to mull this over. The only
> possible solutions I can see are:
>
> a. Make gdbserver "hide" the threads that are children of forks
> until we've reported the corresponding fork event to GDB.
>
Agreed, I think we need to do this. It's somewhat what
linux-nat.c does, except linux-nat.c hides the fork child
until target_follow_fork time.
I say similar, instead of "just like", because the RSP doesn't
have a "follow fork / detach fork" concept. That's because the model
of instead making the child visible as a regular process as soon as we
see the parent fork allows using regular detach, remove breakpoints, etc.
packets against the fork child.
We could make the server always hide the child until it gets some
new "unhide child now" packet, but I think all it would avoid is gdb
looking over the already-reported events and check whether a fork is
pending, so it seems unnecessary.
> But then, I think it's unclear what to do if the user does
> a "step" or "continue" while you have multiple pending
> fork events. That's probably a question that's likely not
> specific to forks, as you might have the same issue when
> requesting an action after seeing the first of multiple
> events received at the same time. Perhaps simply just return
> the next event without resuming anything? Is that what we do?
Yes, that's what we do. For gdb there's no difference between
the other pending event having happened to trigger at the same
time as the last reported event, vs it triggering immediately
on next resume.
>
> b. Somehow enhance GDB to handle the extra unknown threads
> more gracefully.
>
> I don't really see how (b) could work. It seems that (a) would
> be more promising. That said, I would still consider my current
> patch, as reporting the forks early allow us to either detach
> from them earlier.
My usual thought process is this: imagine we had (a) already. Would we
have a particularly strong reason to complicate the code and do (b) on
its own? Seems like not. We could apply the same rationale for preferring
to report any other thread stopped at a breakpoint before the fork
events (so that we could move them past their breakpoints earlier). Or
always prefer the stepping thread, as that's the thread the user is most
interested in (*). Etc.
(*) - IIRC, the reason we prefer a stepped thread first is for correctness,
not because that's what the user is focused in. It used to be that if a step
event got pending, and we reported some other event first, later when the
pending step event is finally reported as a plain SIGTRAP, if the thread that had
a pending step was now continued instead of stepped, infrun wouldn't
understanding what this SIGTRAP was about, since the thread was no longer
supposed to be single-stepping, and would thus report the SIGTRAP to the
user as a spurious signal. With "maint set target-non-stop on", which is still
not the default with target remote, infrun.c:clear_proceed_status_thread
handles this scenario on the gdb side and discards the single-step, but with
plain all-stop, the spurious SIGTRAP probably would still happen.
Thanks,
Pedro Alves