public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFA/LynxOS] GDBserver crash debugging threaded program
@ 2015-11-09 18:17 Joel Brobecker
  2015-11-20 16:11 ` Pedro Alves
  0 siblings, 1 reply; 3+ messages in thread
From: Joel Brobecker @ 2015-11-09 18:17 UTC (permalink / raw)
  To: gdb-patches

Hello,

This crash is observable by debugging a threaded program on LynxOS.
On the GDB side, this is what we would see:

    % gdb q
    (gdb) target remote machine:4444
    (gdb) break q.adb:6
    (gdb) cont
    [gdb hits breakpoint]
    (gdb) cont
    Remote connection closed    <<<--- expected: [Inferior 1 (Remote target) exited normally]

On the gdbserver side, which was launched as usual:

    % gdbserver --once :4444 q
    Segmentation fault (core dumped)

Ooops!

The problem happens while GDB is trying to handle the thread termination
event of the thread that hit the breakpoint. It started happening after
the following change was made:

    commit 96e7a1eb6d09fda9e22e112e35e7d0085a8f4fd0
    Date:   Fri Oct 16 11:08:38 2015 -0400
    Subject: gdbserver: Reset current_thread when the thread is removed.

    Reset current_thread and make sure 'remove_process' is used
    after all associated threads have been removed first.

More precisely:

  . GDBserver receives the execution-resume order;

  . lynx-low resumes it succesfully, and then relies on lynx_wait_1
    to wait for the next event;

  . We quickly receive one, which lynx_wait_1 analyzes to be
    a "thread exit" event, and therefore does...

          case SIGTHREADEXIT:
            remove_thread (find_thread_ptid (new_ptid));
            lynx_continue (new_ptid);
            goto retry;

    => remove_thread causes current_thread to be set to NULL...
       (that's the recent change mentioned above)

    => ... which causes problems during lynx_continue, because
       it calls lynx_resume, which calls regcache_invalidate,
       which unfortunately assumes that CURRENT_THREAD is not NULL:

        void
        regcache_invalidate (void)
        {
          /* Only update the threads of the current process.  */
SEGV!-->  int pid = ptid_get_pid (current_thread->entry.id);

          find_inferior (&all_threads, regcache_invalidate_one, &pid);
        }

Since the problem at hand is caused by trying to figure out which
inferior to reset the regcache for, and since lynx_resume actually
had that info, this patch fixes the problem by introducing a new
routine called regcache_invalidate_pid, which invalidates the cache
of the given pid; and then modifies lynx_resume use that new routine
rather than relying on regcache_invalidate to invalidate the regcache
of the expected inferior.

gdb/gdbserver/ChangeLog:

        * regcache.h (regcache_invalidate_pid): Add declaration.
        * regcache.c (regcache_invalidate_pid): New function, extracted
        from regcache_invalidate.
        (regcache_invalidate): Reimplement using regcache_invalidate_pid.
        Add trivial documentation comment.
        * lynx-low.c: Use regcache_invalidate_pid instead of
        regcache_invalidate.

Tested on ppc-lynxos178. OK to commit?

Note that there are only a handfull calls make to regcache_invalidate
(nto, spu, and win32), and they seem to be made in the same situation
as LynxOS. They could potentially have the same latent bug (although,
I'm not seeing this issue on Windows, at the moment). I think we should
be able to modify the code to use regcache_invalidate_pid instead, but
it's not completely obvious, and I wouldn't be able to test those
changes on nto and spu.

---
 gdb/gdbserver/lynx-low.c |  2 +-
 gdb/gdbserver/regcache.c | 12 +++++++++++-
 gdb/gdbserver/regcache.h |  4 ++++
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index 0582399..36ab0a3 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -343,7 +343,7 @@ lynx_resume (struct thread_resume *resume_info, size_t n)
   if (ptid_equal (ptid, minus_one_ptid))
     ptid = thread_to_gdb_id (current_thread);
 
-  regcache_invalidate ();
+  regcache_invalidate_pid (ptid_get_pid (ptid));
 
   errno = 0;
   lynx_ptrace (request, ptid, 1, signal, 0);
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index e11b173..b9311fe 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -107,13 +107,23 @@ regcache_invalidate_one (struct inferior_list_entry *entry,
   return 0;
 }
 
+/* See regcache.h.  */
+
+void
+regcache_invalidate_pid (int pid)
+{
+  find_inferior (&all_threads, regcache_invalidate_one, &pid);
+}
+
+/* See regcache.h.  */
+
 void
 regcache_invalidate (void)
 {
   /* Only update the threads of the current process.  */
   int pid = ptid_get_pid (current_thread->entry.id);
 
-  find_inferior (&all_threads, regcache_invalidate_one, &pid);
+  regcache_invalidate_pid (pid);
 }
 
 #endif
diff --git a/gdb/gdbserver/regcache.h b/gdb/gdbserver/regcache.h
index d2d9fc7..a0be95e 100644
--- a/gdb/gdbserver/regcache.h
+++ b/gdb/gdbserver/regcache.h
@@ -74,6 +74,10 @@ void free_register_cache (struct regcache *regcache);
 
 void regcache_invalidate_thread (struct thread_info *);
 
+/* Invalidate cached registers for all threads of the given process.  */
+
+void regcache_invalidate_pid (int pid);
+
 /* Invalidate cached registers for all threads of the current
    process.  */
 
-- 
2.1.4

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [RFA/LynxOS] GDBserver crash debugging threaded program
  2015-11-09 18:17 [RFA/LynxOS] GDBserver crash debugging threaded program Joel Brobecker
@ 2015-11-20 16:11 ` Pedro Alves
  2015-11-23 17:57   ` pushed: " Joel Brobecker
  0 siblings, 1 reply; 3+ messages in thread
From: Pedro Alves @ 2015-11-20 16:11 UTC (permalink / raw)
  To: Joel Brobecker, gdb-patches

On 11/09/2015 06:17 PM, Joel Brobecker wrote:

> gdb/gdbserver/ChangeLog:
> 
>         * regcache.h (regcache_invalidate_pid): Add declaration.
>         * regcache.c (regcache_invalidate_pid): New function, extracted
>         from regcache_invalidate.
>         (regcache_invalidate): Reimplement using regcache_invalidate_pid.
>         Add trivial documentation comment.
>         * lynx-low.c: Use regcache_invalidate_pid instead of
>         regcache_invalidate.
> 
> Tested on ppc-lynxos178. OK to commit?

LGTM.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 3+ messages in thread

* pushed: [RFA/LynxOS] GDBserver crash debugging threaded program
  2015-11-20 16:11 ` Pedro Alves
@ 2015-11-23 17:57   ` Joel Brobecker
  0 siblings, 0 replies; 3+ messages in thread
From: Joel Brobecker @ 2015-11-23 17:57 UTC (permalink / raw)
  To: gdb-patches

> > gdb/gdbserver/ChangeLog:
> > 
> >         * regcache.h (regcache_invalidate_pid): Add declaration.
> >         * regcache.c (regcache_invalidate_pid): New function, extracted
> >         from regcache_invalidate.
> >         (regcache_invalidate): Reimplement using regcache_invalidate_pid.
> >         Add trivial documentation comment.
> >         * lynx-low.c: Use regcache_invalidate_pid instead of
> >         regcache_invalidate.
> > 
> > Tested on ppc-lynxos178. OK to commit?
> 
> LGTM.

Thanks, Pedro. The patch has now been pushed.

-- 
Joel

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2015-11-23 17:57 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-09 18:17 [RFA/LynxOS] GDBserver crash debugging threaded program Joel Brobecker
2015-11-20 16:11 ` Pedro Alves
2015-11-23 17:57   ` pushed: " Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).