RE: Crash of GDB with gdbserver btrace enabled [Re: [patch v9 00/23] branch tracing support for Atom]

Metzger, Markus T
2013-03-06T15:31:15Z

> -----Original Message-----
> From: Metzger, Markus T
> Sent: Wednesday, March 06, 2013 3:41 PM

> > ./gdbserver :1234 true
> > ./gdb true -ex 'target remote localhost:1234' -ex 'set debug remote 1' -ex 'record btrace' -ex c
> >
> > will crash GDB. There were a similar thread on the list before, I have not
> > investigated it yet.
> >
> > But this is sure not a regression when btrace is not involved.
>
> Thanks!
>
> Here's the problem..
> When we close the record-btrace target in response to mourn_inferior (should be
> the same for any reason), we iterate over all threads and disable branch tracing for
> each thread.
> If we lose the connection to the remote target, we will pop all targets.
> This has several effects:
> - it will discard all inferiors
> - this will also cause us to disable tracing twice
> - thus we try to switch the remote thread twice
> - here we crash due to an unchecked null pointer access
> - even if we survived this it would free the thread_info we're using for our traversal
> - it will remove all targets so we'll run into an internal error when forwarding
> mourn_inferior to the target after unpushing the record target
>
> We need to disable branch tracing when the thread goes away and when we stop
> recording. I therefore put the disabling into the to_close method. Even if I moved
> this somewhere else, I would still try to talk to the target when freeing the resources
> for a thread that goes away.

If I used a thread_exit notifier instead of adding the call directly to
clear_thread_inferior_resources, I would avoid trying to talk to the target as part of
deleting threads in the above example - since we're deleting threads silently.

I still disable threads in to_close which tries to talk to the target. We would thus still
pop all targets, but we wouldn't try to talk to the target during that, i.e. we would
survive this.

We still die later on since popping all targets discards all threads and thus disrupts
the thread traversal in record-btrace's to_close.

This might be avoided by moving the ALL_THREADS - btrace_disable into some other
function that is only called on "record stop". For all other stop reasons, we would rely
on the cleanup when GDB's threads are discarded.

This might leak resources, though! I don't know when threads are deleted silently
and when not. I also don't know what the thread notifier is meant for, i.e. if I should
have used it in the first place.

This doesn't fix the real problem IMO, but it could avoid this deterministic case.

> As far as I understand, we may lose the connection at any time and for all kinds
> of reasons. It just happens deterministically in the above example. So what we
> would want is to be able to try to talk to the target after the connection has been
> lost without crashing GDB.
>
> Do you know what others are doing to avoid this problem?
>
> Regards,
> Markus.
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052