Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
@ 2006-06-14 10:55 Jan Kratochvil
  2006-06-14 14:25 ` Daniel Jacobowitz
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-06-14 10:55 UTC (permalink / raw)
  To: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1984 bytes --]

Hi all,

right now gdb(1) crashes on execve(2) executed by any -lpthread i386 process
on recent %gs based TLS glibc.

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=182116

(new test case "gdb.threads/thread-lost")
Currently:

# gcc -o ./testsuite/gdb.threads/thread-lost ./testsuite/gdb.threads/thread-lost.c -Wall -lpthread -ggdb3
# ./gdb -nx ./testsuite/gdb.threads/thread-lost
GNU gdb 6.5.50.20060614-cvs
...
(gdb) run
Starting program: /home/lace/redhat/src/gdb/testsuite/gdb.threads/thread-lost
[Thread debugging using libthread_db enabled]
[New Thread -1208801600 (LWP 17677)]
Cannot find user-level thread for LWP 17677: generic error
(gdb) bt
Cannot fetch general-purpose registers for thread -1208801600: generic error

With the patch:

(gdb) run
Starting program: /home/lace/redhat/src/gdb/testsuite/gdb.threads/thread-lost
[Thread debugging using libthread_db enabled]
[New Thread -1208301888 (LWP 18818)]
warning: Original threaded process got lost, dropping threads
EXECUTED
Program exited normally.


It is only a heuristic as execve(2) destroys %gs and gdb(1) fails to find the
no longer existing threads through TLS. Patch will warn and turn off the gdb(1)
threads support if it finds out %gs==0.

On i386 with %gs based TLS NPTLS gdb calls glibc td_ta_map_lwp2thr() which
calls ta_howto_reg_thread_area() (case ta_howto_reg_thread_area).
After execve(2) it retrieves %gs as 0 and fails to ps_get_thread_area()
as its idx must be 6 (glibc TLS descriptor) - value of the first/glibc Linux
kernel GDT_ENTRY_TLS_MIN.
It is now workarounded as to drop threading support if %gs==0.

Do you have an idea for a cleaner solution than this hack of waiting till the
threads are no longer accessible?  Not aware of some indication which kernel
syscall will replace the whole process memory space and the process registers.

It also fixes 11 gdb testsuite failures but these were not analysed from case
to case regarding possible false positives.


Regards,
Jan Kratochvil

[-- Attachment #2: Patch for i386 GDB as of CVS 2006-06-14 --]
[-- Type: text/plain, Size: 7318 bytes --]

Index: i386-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/i386-linux-nat.c,v
retrieving revision 1.69
diff -u -p -r1.69 i386-linux-nat.c
--- i386-linux-nat.c	24 Mar 2006 23:08:16 -0000	1.69
+++ i386-linux-nat.c	14 Jun 2006 10:52:11 -0000
@@ -721,7 +721,19 @@ ps_get_thread_area (const struct ps_proc
 
   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid,
 	      (void *) idx, (unsigned long) &desc) < 0)
-    return PS_ERR;
+    {
+      /* i386: execve(2) will clear the registers including %gs (idx) */
+      if (!idx)
+	{
+	  extern int thread_db_disconnect (void);
+	  if (thread_db_disconnect ())
+	    warning (_("Original threaded process got lost, dropping threads"));
+	  /* Caught by thread_from_lwp() like as TD_THR_ZOMBIE.  */
+	  *(int *)base = 0;
+	  return PS_BADADDR;
+	}
+      return PS_ERR;
+    }
 
   *(int *)base = desc[1];
   return PS_OK;
Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.16
diff -u -p -r1.16 linux-thread-db.c
--- linux-thread-db.c	5 May 2006 22:42:43 -0000	1.16
+++ linux-thread-db.c	14 Jun 2006 10:52:13 -0000
@@ -367,7 +367,12 @@ thread_from_lwp (ptid_t ptid)
 
   gdb_assert (is_lwp (ptid));
 
+  th.th_unique = (psaddr_t) -1;
   err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
+  /* Catch the result from ps_get_thread_area():
+   * Original threaded process got lost, dropping threads  */
+  if (err != TD_OK && th.th_unique == (psaddr_t) 0)
+    return pid_to_ptid (-1);
   if (err != TD_OK)
     error (_("Cannot find user-level thread for LWP %ld: %s"),
 	   GET_LWP (ptid), thread_db_err_str (err));
@@ -1098,22 +1103,36 @@ thread_db_post_startup_inferior (ptid_t 
     }
 }
 
-static void
-thread_db_mourn_inferior (void)
+int
+thread_db_disconnect (void)
 {
+  if (!using_thread_db)
+    return 0;
+
   /* Forget about the child's process ID.  We shouldn't need it
      anymore.  */
   proc_handle.pid = 0;
 
+  /* Detach thread_db target ops.  */
+  unpush_target (&thread_db_ops);
+  using_thread_db = 0;
+
+  return 1;
+}
+
+static void
+thread_db_mourn_inferior (void)
+{
+  int disconnected;
+
   target_beneath->to_mourn_inferior ();
 
   /* Delete the old thread event breakpoints.  Do this after mourning
      the inferior, so that we don't try to uninsert them.  */
   remove_thread_event_breakpoints ();
 
-  /* Detach thread_db target ops.  */
-  unpush_target (&thread_db_ops);
-  using_thread_db = 0;
+  disconnected = thread_db_disconnect ();
+  gdb_assert (disconnected != 0);
 }
 
 static int
Index: testsuite/gdb.threads/thread-lost.c
===================================================================
RCS file: testsuite/gdb.threads/thread-lost.c
diff -N testsuite/gdb.threads/thread-lost.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.threads/thread-lost.c	14 Jun 2006 10:52:18 -0000
@@ -0,0 +1,36 @@
+/* A minimal test case linked with pthreads library.
+
+   Copyright 2006
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <pthread.h>
+#include <unistd.h>
+
+int main()
+{
+  pthread_t thr;
+  char *cmd_argv[] = { "/bin/echo", "EXECUTED", NULL };
+  char *cmd_env[] = { NULL };
+
+  /* Just ensure we are linked with -lpthread. */
+  thr = pthread_self ();
+
+  return execve (cmd_argv[0], cmd_argv, cmd_env);
+}
Index: testsuite/gdb.threads/thread-lost.exp
===================================================================
RCS file: testsuite/gdb.threads/thread-lost.exp
diff -N testsuite/gdb.threads/thread-lost.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gdb.threads/thread-lost.exp	14 Jun 2006 10:52:18 -0000
@@ -0,0 +1,88 @@
+# Copyright (C) 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+# 
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file was written by Jan Kratochvil <lace@jankratochvil.net>.
+#
+# It tests regression of Red Hat Bug 78228, reported again as Bug 182116.
+# On i386 with %gs based TLS NPTLS gdb calls glibc td_ta_map_lwp2thr() which 
+# calls ta_howto_reg_thread_area() (case ta_howto_reg_thread_area).
+# After execve(2) it retrieves %gs as 0 and fails to ps_get_thread_area()
+# as its idx must be 6 (glibc TLS descriptor) - value of the first/glibc Linux
+# kernel GDT_ENTRY_TLS_MIN.
+# It is now workarounded as to drop threading support if %gs==0.
+
+if $tracelevel then {
+	strace $tracelevel
+}
+
+set testfile "thread-lost"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable [list debug "incdir=${objdir}"]] != "" } {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+gdb_run_cmd
+gdb_expect {
+  -re "Original threaded process got lost, dropping threads" {
+    pass "run program to execve(2)"
+  }
+  -re "Cannot find user-level thread for LWP" {
+    fail "GDB did not cope with multithreaded execve(2)"
+  }
+  timeout {
+    fail "run program to execve(2) (timeout)"
+  }
+}
+
+# Only if we would break the execution on:
+# Original threaded process got lost, dropping threads
+###send_gdb "continue\n";
+send_gdb "";
+gdb_expect {
+  -re "EXECUTED" {
+    pass "spawned child got executed"
+  }
+  -re "Cannot find user-level thread for LWP" {
+    fail "GDB did not cope with multithreaded execve(2)"
+  }
+  timeout {
+    fail "spawned child failed to be executed (timeout)"
+  }
+}
+
+send_gdb "quit\n"
+gdb_expect {
+  eof {
+    pass "GDB exits after spawned child finished"
+  }
+  -re "The program is running.  Exit anyway\\? \\(y or n\\) $" {
+    send_gdb "y\n"
+    fail "GDB got stuck after spawned child"
+  }
+  timeout {
+    fail "GDB fails to exit after spawned child"
+  }
+}

[-- Attachment #3: Minimized bug reproducibility test case --]
[-- Type: text/plain, Size: 1142 bytes --]

/* A minimal test case linked with pthreads library.

   Copyright 2006
   Free Software Foundation, Inc.

   This file is part of GDB.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.  */

#include <pthread.h>
#include <unistd.h>

int main()
{
  pthread_t thr;
  char *cmd_argv[] = { "/bin/echo", "EXECUTED", NULL };
  char *cmd_env[] = { NULL };

  /* Just ensure we are linked with -lpthread. */
  thr = pthread_self ();

  return execve (cmd_argv[0], cmd_argv, cmd_env);
}

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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-06-14 10:55 RFC: Fix crash on i386 (%gs-)threaded programs using execve(2) Jan Kratochvil
@ 2006-06-14 14:25 ` Daniel Jacobowitz
  2006-06-15 20:36   ` Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Jacobowitz @ 2006-06-14 14:25 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Wed, Jun 14, 2006 at 12:55:10PM +0200, Jan Kratochvil wrote:
> It is only a heuristic as execve(2) destroys %gs and gdb(1) fails to find the
> no longer existing threads through TLS. Patch will warn and turn off the gdb(1)
> threads support if it finds out %gs==0.
> 
> On i386 with %gs based TLS NPTLS gdb calls glibc td_ta_map_lwp2thr() which
> calls ta_howto_reg_thread_area() (case ta_howto_reg_thread_area).
> After execve(2) it retrieves %gs as 0 and fails to ps_get_thread_area()
> as its idx must be 6 (glibc TLS descriptor) - value of the first/glibc Linux
> kernel GDT_ENTRY_TLS_MIN.
> It is now workarounded as to drop threading support if %gs==0.
> 
> Do you have an idea for a cleaner solution than this hack of waiting till the
> threads are no longer accessible?  Not aware of some indication which kernel
> syscall will replace the whole process memory space and the process registers.

Your problem combines two different issues:

- libthread_db doesn't do anything sensible at the beginning of
execution, before libpthread is initialized.  I filed a bug in the
glibc bugzilla about this with a possible patch.

- gdb thinks threading is still active after an exec.

We already have a way to detect exec events: PTRACE_EVENT_EXEC. 
Support for it is disabled, because it really doesn't work very well,
and no one has volunteered to fix it.  The way we handle it doesn't
make much sense; gdb silently switches the current executable file from
the old program to the new programl which messes up what happens when
the user says "run".

But if you wanted to support any kind of execve debugging, that would
be the way to do it.

Oh, and please don't add more tests to the testsuite which would spin
forever if detached from GDB; we've already got a few and I'm convinced
in hindsight that it was a mistake.  You only need it to exec once, so
you could make it quietly exit the second time.

-- 
Daniel Jacobowitz
CodeSourcery


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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-06-14 14:25 ` Daniel Jacobowitz
@ 2006-06-15 20:36   ` Jan Kratochvil
  2006-07-21 18:16     ` Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-06-15 20:36 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1375 bytes --]

Hi Daniel,

[ regarding debugging of exec*(2) called from programs using -lpthread ]

On Wed, 14 Jun 2006 16:25:52 +0200, Daniel Jacobowitz wrote:
...
> Your problem combines two different issues:
> 
> - libthread_db doesn't do anything sensible at the beginning of
> execution, before libpthread is initialized.  I filed a bug in the
> glibc bugzilla about this with a possible patch.

http://sourceware.org/bugzilla/show_bug.cgi?id=2696

Still I do not see much a problem, gdb(1) just runs in non-threaded mode and
with my patch it properly drops back to the non-threaded mode after exec*(2).


> - gdb thinks threading is still active after an exec.
> 
> We already have a way to detect exec events: PTRACE_EVENT_EXEC. 
> Support for it is disabled, because it really doesn't work very well,

Does the rewritten patch look fine?  Why was follow_exec() enabled only for
HP-UX? (and in fact it would have to be enabled there by hand)

...
> Oh, and please don't add more tests to the testsuite which would spin
> forever if detached from GDB; we've already got a few and I'm convinced
> in hindsight that it was a mistake.  You only need it to exec once, so
> you could make it quietly exit the second time.

I did not understood the problem exactly; I dropped my test case as it is
already tested by the existing (originally HP-UX only) "gdb.base/foll-exec".


Thanks,
Jan

[-- Attachment #2: gdb-cvs20060614-follow_exec.patch --]
[-- Type: text/plain, Size: 5156 bytes --]

Index: inf-ptrace.c
===================================================================
RCS file: /cvs/src/src/gdb/inf-ptrace.c,v
retrieving revision 1.32
diff -u -p -r1.32 inf-ptrace.c
--- inf-ptrace.c	24 Jan 2006 22:34:34 -0000	1.32
+++ inf-ptrace.c	15 Jun 2006 19:49:24 -0000
@@ -166,8 +166,10 @@ inf_ptrace_mourn_inferior (void)
   /* Wait just one more time to collect the inferior's exit status.
      Do not check whether this succeeds though, since we may be
      dealing with a process that we attached to.  Such a process will
-     only report its exit status to its original parent.  */
-  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+     only report its exit status to its original parent.
+     WNOHANG is required as on follow_exec() (due to TARGET_WAITKIND_EXECD)
+     resulted from waitpid(2) and it called us by target_mourn_inferior().  */
+  waitpid (ptid_get_pid (inferior_ptid), &status, WNOHANG);
 
   unpush_target (ptrace_ops_hack);
   generic_mourn_inferior ();
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.210
diff -u -p -r1.210 infrun.c
--- infrun.c	30 Mar 2006 16:37:13 -0000	1.210
+++ infrun.c	15 Jun 2006 19:49:31 -0000
@@ -47,6 +47,7 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "objfiles.h"
 
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
@@ -109,10 +110,10 @@ int sync_execution = 0;
 static ptid_t previous_inferior_ptid;
 
 /* This is true for configurations that may follow through execl() and
-   similar functions.  At present this is only true for HP-UX native.  */
+   similar functions.  */
 
 #ifndef MAY_FOLLOW_EXEC
-#define MAY_FOLLOW_EXEC (0)
+#define MAY_FOLLOW_EXEC (1)
 #endif
 
 static int may_follow_exec = MAY_FOLLOW_EXEC;
@@ -382,6 +383,7 @@ follow_exec (int pid, char *execd_pathna
 {
   int saved_pid = pid;
   struct target_ops *tgt;
+  struct objfile *objfile, *objfile_temp;
 
   if (!may_follow_exec)
     return;
@@ -427,6 +429,19 @@ follow_exec (int pid, char *execd_pathna
     error (_("Could find run target to save before following exec"));
 
   gdb_flush (gdb_stdout);
+
+  /* As symbol_file_add_main()->thread_db_new_objfile()->check_for_thread_db()
+   * would fine already loaded libpthread.so while the threading structures
+   * would not be yet initialized for this early inferior.
+   * Call before target_mourn_inferior() as it will breakpoint_re_set().  */
+  clear_solib ();
+  /* Do not: symbol_file_clear()->clear_symtab_users()->breakpoint_re_set().  */
+  ALL_OBJFILES_SAFE (objfile, objfile_temp)
+  {
+    free_objfile (objfile);
+  }
+  symfile_objfile = NULL;
+
   target_mourn_inferior ();
   inferior_ptid = pid_to_ptid (saved_pid);
   /* Because mourn_inferior resets inferior_ptid. */
Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.16
diff -u -p -r1.16 linux-thread-db.c
--- linux-thread-db.c	5 May 2006 22:42:43 -0000	1.16
+++ linux-thread-db.c	15 Jun 2006 19:49:33 -0000
@@ -945,6 +945,10 @@ thread_db_wait (ptid_t ptid, struct targ
   if (ourstatus->kind == TARGET_WAITKIND_EXITED)
     return pid_to_ptid (-1);
 
+  /* Threading structures got reset.  Return as nonthreaded.  */
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    return pid_to_ptid (GET_PID (ptid));
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */
@@ -1111,6 +1115,9 @@ thread_db_mourn_inferior (void)
      the inferior, so that we don't try to uninsert them.  */
   remove_thread_event_breakpoints ();
 
+  /* Destroy thread info; it's no longer valid.  */
+  init_thread_list ();
+
   /* Detach thread_db target ops.  */
   unpush_target (&thread_db_ops);
   using_thread_db = 0;
Index: testsuite/gdb.base/foll-exec.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/foll-exec.exp,v
retrieving revision 1.2
diff -u -p -r1.2 foll-exec.exp
--- testsuite/gdb.base/foll-exec.exp	6 Mar 2001 08:21:50 -0000	1.2
+++ testsuite/gdb.base/foll-exec.exp	15 Jun 2006 19:49:34 -0000
@@ -45,12 +45,6 @@ if  { [gdb_compile "${srcdir}/${subdir}/
 }
 
 
-# Until "catch exec" is implemented on other targets...
-#
-if ![istarget "hppa*-hp-hpux*"] then {
-    continue
-}
-
 proc zap_session {} {
    global gdb_prompt
    global binfile
@@ -212,7 +206,9 @@ proc do_exec_tests {} {
    setup_xfail hppa2.0w-hp-hpux* CLLbs16760
    send_gdb "continue\n"
    gdb_expect {
-     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\
+     # It is OS dependent and no symbols may be found, GNU/Linux has "_start"
+     # while HP-UX has " in .START..*$gdb_prompt" etc.
+     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .*$gdb_prompt $"\
                      {pass "hit catch exec"}
      -re "$gdb_prompt $" {fail "hit catch exec"}
      timeout         {fail "(timeout) hit catch exec"}

[-- Attachment #3: gdb.sum.diff --]
[-- Type: text/plain, Size: 6994 bytes --]

--- -	2006-06-15 21:42:30.996632000 +0200
+++ testsuite/gdb.sum	2006-06-15 21:33:45.000000000 +0200
@@ -1,4 +1,4 @@
-Test Run By lace on Wed Jun 14 08:49:44 2006
+Test Run By lace on Thu Jun 15 21:19:26 2006
 Native configuration is i686-pc-linux-gnu
 
 		=== gdb tests ===
@@ -385,8 +385,8 @@
 PASS: gdb.base/bigcore.exp: tbreak 264
 PASS: gdb.base/bigcore.exp: continue
 PASS: gdb.base/bigcore.exp: next
-PASS: gdb.base/bigcore.exp: extract next heap (stop at 50)
-PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50)
+PASS: gdb.base/bigcore.exp: extract next heap
+PASS: gdb.base/bigcore.exp: extract prev heap
 PASS: gdb.base/bigcore.exp: save heap size
 PASS: gdb.base/bigcore.exp: grab pid
 PASS: gdb.base/bigcore.exp: signal SIGABRT
@@ -2730,6 +2730,33 @@
 Running ../.././gdb/testsuite/gdb.base/float.exp ...
 PASS: gdb.base/float.exp: info float
 Running ../.././gdb/testsuite/gdb.base/foll-exec.exp ...
+PASS: gdb.base/foll-exec.exp: step to exec call
+PASS: gdb.base/foll-exec.exp: print follow-exec/global_i
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_j
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_k
+PASS: gdb.base/foll-exec.exp: step through execlp call
+PASS: gdb.base/foll-exec.exp: step after execlp call
+PASS: gdb.base/foll-exec.exp: print execd-program/global_i (after execlp)
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execlp)
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_k (after execlp)
+PASS: gdb.base/foll-exec.exp: set catch exec
+PASS: gdb.base/foll-exec.exp: info shows catchpoint without exec pathname
+PASS: gdb.base/foll-exec.exp: hit catch exec
+PASS: gdb.base/foll-exec.exp: sync up after possible failure 1
+PASS: gdb.base/foll-exec.exp: sync up after possible failure 2
+PASS: gdb.base/foll-exec.exp: info shows catchpoint exec pathname
+PASS: gdb.base/foll-exec.exp: continue after hit catch exec
+PASS: gdb.base/foll-exec.exp: prepare to jump to execl call
+PASS: gdb.base/foll-exec.exp: jump to execl call
+PASS: gdb.base/foll-exec.exp: step through execl call
+PASS: gdb.base/foll-exec.exp: step after execl call
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execl)
+PASS: gdb.base/foll-exec.exp: prepare to jump to execv call
+PASS: gdb.base/foll-exec.exp: jump to execv call
+PASS: gdb.base/foll-exec.exp: step through execv call
+PASS: gdb.base/foll-exec.exp: step after execv call
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execv)
+PASS: gdb.base/foll-exec.exp: continue through exec
 Running ../.././gdb/testsuite/gdb.base/foll-fork.exp ...
 Running ../.././gdb/testsuite/gdb.base/foll-vfork.exp ...
 Running ../.././gdb/testsuite/gdb.base/freebpcmd.exp ...
@@ -11226,16 +11253,27 @@
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (fast)
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (fast)
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (fast)
-FAIL: gdb.threads/print-threads.exp: Running threads (fast) (unknown output)
-FAIL: gdb.threads/print-threads.exp: setting breakpoint at main
-FAIL: gdb.threads/print-threads.exp: break thread_function (2)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (fast)
+PASS: gdb.threads/print-threads.exp: break thread_function (2)
 PASS: gdb.threads/print-threads.exp: set var slow = 1
-FAIL: gdb.threads/print-threads.exp: Running threads (slow) (unknown output)
-FAIL: gdb.threads/print-threads.exp: setting breakpoint at main
-FAIL: gdb.threads/print-threads.exp: break thread_function (3)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 1 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 2 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (slow)
+PASS: gdb.threads/print-threads.exp: break thread_function (3)
 PASS: gdb.threads/print-threads.exp: set var slow = 1 (2)
-FAIL: gdb.threads/print-threads.exp: break kill
-FAIL: gdb.threads/print-threads.exp: Running threads (slow with kill breakpoint) (unknown output)
+PASS: gdb.threads/print-threads.exp: break kill
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 1 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 2 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (slow with kill breakpoint)
 Running ../.././gdb/testsuite/gdb.threads/pthread_cond_wait.exp ...
 PASS: gdb.threads/pthread_cond_wait.exp: successfully compiled posix threads test case
 PASS: gdb.threads/pthread_cond_wait.exp: breakpoint on break_me
@@ -11356,7 +11394,7 @@
 PASS: gdb.threads/staticthreads.exp: rerun to main
 PASS: gdb.threads/staticthreads.exp: handle SIG32 nostop noprint pass
 FAIL: gdb.threads/staticthreads.exp: handle SIG32 helps
-KFAIL: gdb.threads/staticthreads.exp: info threads (PRMS: gdb/1328)
+PASS: gdb.threads/staticthreads.exp: info threads
 PASS: gdb.threads/staticthreads.exp: GDB exits with static thread program
 Running ../.././gdb/testsuite/gdb.threads/step.exp ...
 Running ../.././gdb/testsuite/gdb.threads/step2.exp ...
@@ -11454,9 +11492,8 @@
 PASS: gdb.threads/tls.exp: 3 info address another_thread_local
 PASS: gdb.threads/tls.exp: threads exited
 PASS: gdb.threads/tls.exp: Expect only base thread at end
-FAIL: gdb.threads/tls.exp: running to spin in runto (timeout)
-FAIL: gdb.threads/tls.exp: info address a_global (timeout)
-KFAIL: gdb.threads/tls.exp: info address me (timeout) (PRMS: gdb/1294)
+PASS: gdb.threads/tls.exp: info address a_global
+KFAIL: gdb.threads/tls.exp: info address me (PRMS: gdb/1294)
 Running ../.././gdb/testsuite/gdb.threads/watchthreads.exp ...
 PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case
 PASS: gdb.threads/watchthreads.exp: watch args[0]
@@ -11608,12 +11645,12 @@
 
 		=== gdb Summary ===
 
-# of expected passes		11048
-# of unexpected failures	52
+# of expected passes		11096
+# of unexpected failures	42
 # of unexpected successes	1
 # of expected failures		42
 # of unknown successes		9
-# of known failures		75
+# of known failures		74
 # of untested testcases		4
 # of unsupported tests		13
 /home/lace/redhat/src/gdb/testsuite/../../gdb/gdb version  6.5.50.20060614-cvs -nx

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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-06-15 20:36   ` Jan Kratochvil
@ 2006-07-21 18:16     ` Jan Kratochvil
  2006-07-21 18:44       ` Daniel Jacobowitz
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-07-21 18:16 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1710 bytes --]

Hi Daniel,

I am now copyright assignment compliant (as Red Hat employee).

The mail below was never replied; the patch still applies to the latest CVS.
Could you please review it?


Thanks,
Jan


On Thu, 15 Jun 2006 22:35:20 +0200, Jan Kratochvil wrote:
------------------------------------------------------------------------------

Hi Daniel,

[ regarding debugging of exec*(2) called from programs using -lpthread ]

On Wed, 14 Jun 2006 16:25:52 +0200, Daniel Jacobowitz wrote:
...
> Your problem combines two different issues:
> 
> - libthread_db doesn't do anything sensible at the beginning of
> execution, before libpthread is initialized.  I filed a bug in the
> glibc bugzilla about this with a possible patch.

http://sourceware.org/bugzilla/show_bug.cgi?id=2696

Still I do not see much a problem, gdb(1) just runs in non-threaded mode and
with my patch it properly drops back to the non-threaded mode after exec*(2).


> - gdb thinks threading is still active after an exec.
> 
> We already have a way to detect exec events: PTRACE_EVENT_EXEC. 
> Support for it is disabled, because it really doesn't work very well,

Does the rewritten patch look fine?  Why was follow_exec() enabled only for
HP-UX? (and in fact it would have to be enabled there by hand)

...
> Oh, and please don't add more tests to the testsuite which would spin
> forever if detached from GDB; we've already got a few and I'm convinced
> in hindsight that it was a mistake.  You only need it to exec once, so
> you could make it quietly exit the second time.

I did not understood the problem exactly; I dropped my test case as it is
already tested by the existing (originally HP-UX only) "gdb.base/foll-exec".


Thanks,
Jan

[-- Attachment #2: gdb-cvs20060614-follow_exec.patch --]
[-- Type: text/plain, Size: 5156 bytes --]

Index: inf-ptrace.c
===================================================================
RCS file: /cvs/src/src/gdb/inf-ptrace.c,v
retrieving revision 1.32
diff -u -p -r1.32 inf-ptrace.c
--- inf-ptrace.c	24 Jan 2006 22:34:34 -0000	1.32
+++ inf-ptrace.c	15 Jun 2006 19:49:24 -0000
@@ -166,8 +166,10 @@ inf_ptrace_mourn_inferior (void)
   /* Wait just one more time to collect the inferior's exit status.
      Do not check whether this succeeds though, since we may be
      dealing with a process that we attached to.  Such a process will
-     only report its exit status to its original parent.  */
-  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+     only report its exit status to its original parent.
+     WNOHANG is required as on follow_exec() (due to TARGET_WAITKIND_EXECD)
+     resulted from waitpid(2) and it called us by target_mourn_inferior().  */
+  waitpid (ptid_get_pid (inferior_ptid), &status, WNOHANG);
 
   unpush_target (ptrace_ops_hack);
   generic_mourn_inferior ();
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.210
diff -u -p -r1.210 infrun.c
--- infrun.c	30 Mar 2006 16:37:13 -0000	1.210
+++ infrun.c	15 Jun 2006 19:49:31 -0000
@@ -47,6 +47,7 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "objfiles.h"
 
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
@@ -109,10 +110,10 @@ int sync_execution = 0;
 static ptid_t previous_inferior_ptid;
 
 /* This is true for configurations that may follow through execl() and
-   similar functions.  At present this is only true for HP-UX native.  */
+   similar functions.  */
 
 #ifndef MAY_FOLLOW_EXEC
-#define MAY_FOLLOW_EXEC (0)
+#define MAY_FOLLOW_EXEC (1)
 #endif
 
 static int may_follow_exec = MAY_FOLLOW_EXEC;
@@ -382,6 +383,7 @@ follow_exec (int pid, char *execd_pathna
 {
   int saved_pid = pid;
   struct target_ops *tgt;
+  struct objfile *objfile, *objfile_temp;
 
   if (!may_follow_exec)
     return;
@@ -427,6 +429,19 @@ follow_exec (int pid, char *execd_pathna
     error (_("Could find run target to save before following exec"));
 
   gdb_flush (gdb_stdout);
+
+  /* As symbol_file_add_main()->thread_db_new_objfile()->check_for_thread_db()
+   * would fine already loaded libpthread.so while the threading structures
+   * would not be yet initialized for this early inferior.
+   * Call before target_mourn_inferior() as it will breakpoint_re_set().  */
+  clear_solib ();
+  /* Do not: symbol_file_clear()->clear_symtab_users()->breakpoint_re_set().  */
+  ALL_OBJFILES_SAFE (objfile, objfile_temp)
+  {
+    free_objfile (objfile);
+  }
+  symfile_objfile = NULL;
+
   target_mourn_inferior ();
   inferior_ptid = pid_to_ptid (saved_pid);
   /* Because mourn_inferior resets inferior_ptid. */
Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.16
diff -u -p -r1.16 linux-thread-db.c
--- linux-thread-db.c	5 May 2006 22:42:43 -0000	1.16
+++ linux-thread-db.c	15 Jun 2006 19:49:33 -0000
@@ -945,6 +945,10 @@ thread_db_wait (ptid_t ptid, struct targ
   if (ourstatus->kind == TARGET_WAITKIND_EXITED)
     return pid_to_ptid (-1);
 
+  /* Threading structures got reset.  Return as nonthreaded.  */
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    return pid_to_ptid (GET_PID (ptid));
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */
@@ -1111,6 +1115,9 @@ thread_db_mourn_inferior (void)
      the inferior, so that we don't try to uninsert them.  */
   remove_thread_event_breakpoints ();
 
+  /* Destroy thread info; it's no longer valid.  */
+  init_thread_list ();
+
   /* Detach thread_db target ops.  */
   unpush_target (&thread_db_ops);
   using_thread_db = 0;
Index: testsuite/gdb.base/foll-exec.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/foll-exec.exp,v
retrieving revision 1.2
diff -u -p -r1.2 foll-exec.exp
--- testsuite/gdb.base/foll-exec.exp	6 Mar 2001 08:21:50 -0000	1.2
+++ testsuite/gdb.base/foll-exec.exp	15 Jun 2006 19:49:34 -0000
@@ -45,12 +45,6 @@ if  { [gdb_compile "${srcdir}/${subdir}/
 }
 
 
-# Until "catch exec" is implemented on other targets...
-#
-if ![istarget "hppa*-hp-hpux*"] then {
-    continue
-}
-
 proc zap_session {} {
    global gdb_prompt
    global binfile
@@ -212,7 +206,9 @@ proc do_exec_tests {} {
    setup_xfail hppa2.0w-hp-hpux* CLLbs16760
    send_gdb "continue\n"
    gdb_expect {
-     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\
+     # It is OS dependent and no symbols may be found, GNU/Linux has "_start"
+     # while HP-UX has " in .START..*$gdb_prompt" etc.
+     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .*$gdb_prompt $"\
                      {pass "hit catch exec"}
      -re "$gdb_prompt $" {fail "hit catch exec"}
      timeout         {fail "(timeout) hit catch exec"}

[-- Attachment #3: gdb.sum.diff --]
[-- Type: text/plain, Size: 6994 bytes --]

--- -	2006-06-15 21:42:30.996632000 +0200
+++ testsuite/gdb.sum	2006-06-15 21:33:45.000000000 +0200
@@ -1,4 +1,4 @@
-Test Run By lace on Wed Jun 14 08:49:44 2006
+Test Run By lace on Thu Jun 15 21:19:26 2006
 Native configuration is i686-pc-linux-gnu
 
 		=== gdb tests ===
@@ -385,8 +385,8 @@
 PASS: gdb.base/bigcore.exp: tbreak 264
 PASS: gdb.base/bigcore.exp: continue
 PASS: gdb.base/bigcore.exp: next
-PASS: gdb.base/bigcore.exp: extract next heap (stop at 50)
-PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50)
+PASS: gdb.base/bigcore.exp: extract next heap
+PASS: gdb.base/bigcore.exp: extract prev heap
 PASS: gdb.base/bigcore.exp: save heap size
 PASS: gdb.base/bigcore.exp: grab pid
 PASS: gdb.base/bigcore.exp: signal SIGABRT
@@ -2730,6 +2730,33 @@
 Running ../.././gdb/testsuite/gdb.base/float.exp ...
 PASS: gdb.base/float.exp: info float
 Running ../.././gdb/testsuite/gdb.base/foll-exec.exp ...
+PASS: gdb.base/foll-exec.exp: step to exec call
+PASS: gdb.base/foll-exec.exp: print follow-exec/global_i
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_j
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_k
+PASS: gdb.base/foll-exec.exp: step through execlp call
+PASS: gdb.base/foll-exec.exp: step after execlp call
+PASS: gdb.base/foll-exec.exp: print execd-program/global_i (after execlp)
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execlp)
+PASS: gdb.base/foll-exec.exp: print follow-exec/local_k (after execlp)
+PASS: gdb.base/foll-exec.exp: set catch exec
+PASS: gdb.base/foll-exec.exp: info shows catchpoint without exec pathname
+PASS: gdb.base/foll-exec.exp: hit catch exec
+PASS: gdb.base/foll-exec.exp: sync up after possible failure 1
+PASS: gdb.base/foll-exec.exp: sync up after possible failure 2
+PASS: gdb.base/foll-exec.exp: info shows catchpoint exec pathname
+PASS: gdb.base/foll-exec.exp: continue after hit catch exec
+PASS: gdb.base/foll-exec.exp: prepare to jump to execl call
+PASS: gdb.base/foll-exec.exp: jump to execl call
+PASS: gdb.base/foll-exec.exp: step through execl call
+PASS: gdb.base/foll-exec.exp: step after execl call
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execl)
+PASS: gdb.base/foll-exec.exp: prepare to jump to execv call
+PASS: gdb.base/foll-exec.exp: jump to execv call
+PASS: gdb.base/foll-exec.exp: step through execv call
+PASS: gdb.base/foll-exec.exp: step after execv call
+PASS: gdb.base/foll-exec.exp: print execd-program/local_j (after execv)
+PASS: gdb.base/foll-exec.exp: continue through exec
 Running ../.././gdb/testsuite/gdb.base/foll-fork.exp ...
 Running ../.././gdb/testsuite/gdb.base/foll-vfork.exp ...
 Running ../.././gdb/testsuite/gdb.base/freebpcmd.exp ...
@@ -11226,16 +11253,27 @@
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (fast)
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (fast)
 PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (fast)
-FAIL: gdb.threads/print-threads.exp: Running threads (fast) (unknown output)
-FAIL: gdb.threads/print-threads.exp: setting breakpoint at main
-FAIL: gdb.threads/print-threads.exp: break thread_function (2)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (fast)
+PASS: gdb.threads/print-threads.exp: break thread_function (2)
 PASS: gdb.threads/print-threads.exp: set var slow = 1
-FAIL: gdb.threads/print-threads.exp: Running threads (slow) (unknown output)
-FAIL: gdb.threads/print-threads.exp: setting breakpoint at main
-FAIL: gdb.threads/print-threads.exp: break thread_function (3)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 1 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 2 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (slow)
+PASS: gdb.threads/print-threads.exp: break thread_function (3)
 PASS: gdb.threads/print-threads.exp: set var slow = 1 (2)
-FAIL: gdb.threads/print-threads.exp: break kill
-FAIL: gdb.threads/print-threads.exp: Running threads (slow with kill breakpoint) (unknown output)
+PASS: gdb.threads/print-threads.exp: break kill
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 1 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 2 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 3 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 4 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: Hit thread_function breakpoint, 5 (slow with kill breakpoint)
+PASS: gdb.threads/print-threads.exp: program exited normally
+PASS: gdb.threads/print-threads.exp: all threads ran once (slow with kill breakpoint)
 Running ../.././gdb/testsuite/gdb.threads/pthread_cond_wait.exp ...
 PASS: gdb.threads/pthread_cond_wait.exp: successfully compiled posix threads test case
 PASS: gdb.threads/pthread_cond_wait.exp: breakpoint on break_me
@@ -11356,7 +11394,7 @@
 PASS: gdb.threads/staticthreads.exp: rerun to main
 PASS: gdb.threads/staticthreads.exp: handle SIG32 nostop noprint pass
 FAIL: gdb.threads/staticthreads.exp: handle SIG32 helps
-KFAIL: gdb.threads/staticthreads.exp: info threads (PRMS: gdb/1328)
+PASS: gdb.threads/staticthreads.exp: info threads
 PASS: gdb.threads/staticthreads.exp: GDB exits with static thread program
 Running ../.././gdb/testsuite/gdb.threads/step.exp ...
 Running ../.././gdb/testsuite/gdb.threads/step2.exp ...
@@ -11454,9 +11492,8 @@
 PASS: gdb.threads/tls.exp: 3 info address another_thread_local
 PASS: gdb.threads/tls.exp: threads exited
 PASS: gdb.threads/tls.exp: Expect only base thread at end
-FAIL: gdb.threads/tls.exp: running to spin in runto (timeout)
-FAIL: gdb.threads/tls.exp: info address a_global (timeout)
-KFAIL: gdb.threads/tls.exp: info address me (timeout) (PRMS: gdb/1294)
+PASS: gdb.threads/tls.exp: info address a_global
+KFAIL: gdb.threads/tls.exp: info address me (PRMS: gdb/1294)
 Running ../.././gdb/testsuite/gdb.threads/watchthreads.exp ...
 PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case
 PASS: gdb.threads/watchthreads.exp: watch args[0]
@@ -11608,12 +11645,12 @@
 
 		=== gdb Summary ===
 
-# of expected passes		11048
-# of unexpected failures	52
+# of expected passes		11096
+# of unexpected failures	42
 # of unexpected successes	1
 # of expected failures		42
 # of unknown successes		9
-# of known failures		75
+# of known failures		74
 # of untested testcases		4
 # of unsupported tests		13
 /home/lace/redhat/src/gdb/testsuite/../../gdb/gdb version  6.5.50.20060614-cvs -nx

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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-07-21 18:16     ` Jan Kratochvil
@ 2006-07-21 18:44       ` Daniel Jacobowitz
  2006-07-22 12:31         ` Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Jacobowitz @ 2006-07-21 18:44 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Fri, Jul 21, 2006 at 08:15:57PM +0200, Jan Kratochvil wrote:
> Hi Daniel,
> 
> I am now copyright assignment compliant (as Red Hat employee).
> 
> The mail below was never replied; the patch still applies to the latest CVS.
> Could you please review it?

Turning on MAY_FOLLOW_EXEC is not a good idea.  No one really knows how
that behavior works, a lot of it doesn't, and the way it implicitly
changes the symbol file is very disorienting.  Please don't mix it up
with the fix for your current bug.

It seems to me that you need thread_db_wait to check for EXECD, and pop
the threading target off the stack when it happens.  Maybe, if you want
to be fancy, figure out the right place to push itself back on - but
that's more troublesome to get right.

unpush_target (&thread_db_ops);
using_thread_db = 0;
wipe the thread list?;
return some the underlying process pid;

-- 
Daniel Jacobowitz
CodeSourcery


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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-07-21 18:44       ` Daniel Jacobowitz
@ 2006-07-22 12:31         ` Jan Kratochvil
  2006-07-24 19:03           ` Daniel Jacobowitz
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-07-22 12:31 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 1107 bytes --]

Hi Daniel,

please commit if appropriate:

Created the attached minimal patch fixing the gdb lockup.

2006-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linux-thread-db.c (thread_db_wait): Avoid locking up on stale
	threading state after TARGET_WAITKIND_EXECD.

No testsuite case, waiting on MAY_FOLLOW_EXEC resolution below.


On Fri, 21 Jul 2006 20:44:21 +0200, Daniel Jacobowitz wrote:
...
> Turning on MAY_FOLLOW_EXEC is not a good idea.  No one really knows how
> that behavior works, a lot of it doesn't, and the way it implicitly
> changes the symbol file is very disorienting.  Please don't mix it up
> with the fix for your current bug.

Still I am for MAY_FOLLOW_EXEC as it improves the user experience and makes
debugging of exec()ing processes much more convenient - without having to find
out how each child gets executed and replay such conditions by hand.

As gdb-6.5 has been released and the MAY_FOLLOW_EXEC feature IMO generally
works for GNU/Linux - isn't appropriate to enable it and settle it down?
I would even like to fix any issues possibly roaring its head.


Regards,
Jan

[-- Attachment #2: gdb-cvs20060722-exec_reset.patch --]
[-- Type: text/plain, Size: 1102 bytes --]

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=182116

exec() causes fatal:
	Cannot find user-level thread for LWP 4256: generic error
Patch below does not enable the new process tracing but it will not crash.
MAY_FOLLOW_EXEC enable for GNU/Linux was discouraged by Daniel Jacobowitz.
	<20060721184421.GA22820@nevyn.them.org>


Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.17
diff -u -p -r1.17 linux-thread-db.c
--- linux-thread-db.c	18 Jul 2006 22:53:20 -0000	1.17
+++ linux-thread-db.c	22 Jul 2006 12:17:50 -0000
@@ -875,6 +875,14 @@ thread_db_wait (ptid_t ptid, struct targ
   if (ourstatus->kind == TARGET_WAITKIND_EXITED)
     return pid_to_ptid (-1);
 
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    {
+      unpush_target (&thread_db_ops);
+      using_thread_db = 0;
+
+      return pid_to_ptid (GET_PID (ptid));
+    }
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */

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

* Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)
  2006-07-22 12:31         ` Jan Kratochvil
@ 2006-07-24 19:03           ` Daniel Jacobowitz
  2006-07-29 18:54             ` [patch] Linux MAY_FOLLOW_EXEC #2 [Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)] Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Daniel Jacobowitz @ 2006-07-24 19:03 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Sat, Jul 22, 2006 at 02:31:02PM +0200, Jan Kratochvil wrote:
> Hi Daniel,
> 
> please commit if appropriate:
> 
> Created the attached minimal patch fixing the gdb lockup.
> 
> 2006-07-22  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* linux-thread-db.c (thread_db_wait): Avoid locking up on stale
> 	threading state after TARGET_WAITKIND_EXECD.

Thanks.  I've committed the attached version; I played around with it a
little bit, and discovered that you couldn't re-run unless you remember
to remove the thread breakpoints too.

> On Fri, 21 Jul 2006 20:44:21 +0200, Daniel Jacobowitz wrote:
> ...
> > Turning on MAY_FOLLOW_EXEC is not a good idea.  No one really knows how
> > that behavior works, a lot of it doesn't, and the way it implicitly
> > changes the symbol file is very disorienting.  Please don't mix it up
> > with the fix for your current bug.
> 
> Still I am for MAY_FOLLOW_EXEC as it improves the user experience and makes
> debugging of exec()ing processes much more convenient - without having to find
> out how each child gets executed and replay such conditions by hand.
> 
> As gdb-6.5 has been released and the MAY_FOLLOW_EXEC feature IMO generally
> works for GNU/Linux - isn't appropriate to enable it and settle it down?
> I would even like to fix any issues possibly roaring its head.

Does anyone else have an opinion on this?  I'm starting to think you're
right - we should turn it on, invite people to use it, and see what
happens.

The reason I find it so disorienting is this:

% gdb file1

(gdb) run
[starts file1]
[file1 execs file2]
[file2 exits]

(gdb) run
[file2 starts instead of file1!]

I don't know if it should do that or not.  I tend to use "run" a lot
and want to get back to the beginning of my debug session.

-- 
Daniel Jacobowitz
CodeSourcery

2006-07-24  Jan Kratochvil  <jan.kratochvil@redhat.com>
	    Daniel Jacobowitz  <dan@codesourcery.com>

	* linux-thread-db.c (thread_db_wait): Remove libthread_db
	after exec events.

Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.17
diff -u -p -r1.17 linux-thread-db.c
--- linux-thread-db.c	18 Jul 2006 22:53:20 -0000	1.17
+++ linux-thread-db.c	24 Jul 2006 18:56:24 -0000
@@ -875,6 +875,15 @@ thread_db_wait (ptid_t ptid, struct targ
   if (ourstatus->kind == TARGET_WAITKIND_EXITED)
     return pid_to_ptid (-1);
 
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    {
+      remove_thread_event_breakpoints ();
+      unpush_target (&thread_db_ops);
+      using_thread_db = 0;
+
+      return pid_to_ptid (GET_PID (ptid));
+    }
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */


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

* [patch] Linux MAY_FOLLOW_EXEC #2  [Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)]
  2006-07-24 19:03           ` Daniel Jacobowitz
@ 2006-07-29 18:54             ` Jan Kratochvil
  2006-07-31 20:39               ` Mark Kettenis
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-07-29 18:54 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 2358 bytes --]

Hi Daniel,

On Mon, 24 Jul 2006 21:03:32 +0200, Daniel Jacobowitz wrote:
...
> The reason I find it so disorienting is this:
> 
> % gdb file1
> 
> (gdb) run
> [starts file1]
> [file1 execs file2]
> [file2 exits]
> 
> (gdb) run
> [file2 starts instead of file1!]
> 
> I don't know if it should do that or not.  I tend to use "run" a lot
> and want to get back to the beginning of my debug session.

Included restoration patch using make_run_cleanup(), session log below.

That waitpid(3) WNOHANG smells there for me but it does not hurt the testsuite.
Should I investigate it more?

2006-07-29  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* inf-ptrace.c (inf_ptrace_mourn_inferior): waitpid(3) with WNOHANG
	to avoid lockup on the introduced TARGET_WAITKIND_EXECD handling.
	* infrun.c (follow_exec): Unconditionally enabled by MAY_FOLLOW_EXEC.
	Provide restoration of exec_bfd and symfile_objfile for any new "run".
	* linux-thread-db.c (thread_db_wait): Handle TARGET_WAITKIND_EXECD.
	* linux-thread-db.c (thread_db_mourn_inferior): Turn off threading.
	* foll-exec.exp: Uncoditionally enabled for all platforms.
	Relaxed regex to apply besides HP-UX also for GNU/Linux backtrace.


Thanks,
Jan

------------------------------------------------------------------------------

(gdb) file execve
Reading symbols from /tmp/execve...done.
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) catch exec
Catchpoint 1 (exec)
(gdb) set args gdb-entered parameters
(gdb) run
Starting program: /tmp/execve gdb-entered parameters
Executing new program: /tmp/hello
[Switching to process 16524]
Catchpoint 1 (exec'd /tmp/hello), 0x44031840 in ?? ()
(gdb) show args
Argument list to give program being debugged when it is started is "gdb-entered parameters".
(gdb) info files
Symbols from "/tmp/hello".
Unix child process:
	Using the running image of child process 16524.
	While running this, GDB does not access memory from...
Local exec file:
	`/tmp/hello', file type elf32-i386.
[...]
(gdb) c
Continuing.
[New process 16524]
hello world

Program exited normally.
(gdb) info files
Symbols from "/tmp/hello".
Local exec file:
	`/tmp/hello', file type elf32-i386.
[...]
(gdb) run
Starting program: /tmp/execve gdb-entered parameters
Executing new program: /tmp/hello
[Switching to process 16827]

Catchpoint 1 (exec'd /tmp/hello), 0x44031840 in ?? ()
(gdb)

[-- Attachment #2: gdb-6.5-follow-exec.patch --]
[-- Type: text/plain, Size: 6552 bytes --]

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=182116


diff -rup gdb-6.5-orig/gdb/inf-ptrace.c gdb-6.5-follow_exec/gdb/inf-ptrace.c
--- gdb-6.5-orig/gdb/inf-ptrace.c	2006-01-24 23:34:34.000000000 +0100
+++ gdb-6.5-follow_exec/gdb/inf-ptrace.c	2006-07-29 11:26:32.000000000 +0200
@@ -166,8 +166,10 @@ inf_ptrace_mourn_inferior (void)
   /* Wait just one more time to collect the inferior's exit status.
      Do not check whether this succeeds though, since we may be
      dealing with a process that we attached to.  Such a process will
-     only report its exit status to its original parent.  */
-  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+     only report its exit status to its original parent.
+     WNOHANG is required as on follow_exec() (due to TARGET_WAITKIND_EXECD)
+     resulted from waitpid(2) and it called us by target_mourn_inferior().  */
+  waitpid (ptid_get_pid (inferior_ptid), &status, WNOHANG);
 
   unpush_target (ptrace_ops_hack);
   generic_mourn_inferior ();
diff -rup gdb-6.5-orig/gdb/infrun.c gdb-6.5-follow_exec/gdb/infrun.c
--- gdb-6.5-orig/gdb/infrun.c	2006-07-28 23:30:22.000000000 +0200
+++ gdb-6.5-follow_exec/gdb/infrun.c	2006-07-29 19:06:06.000000000 +0200
@@ -47,6 +47,7 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "objfiles.h"
 
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
@@ -109,10 +110,10 @@ int sync_execution = 0;
 static ptid_t previous_inferior_ptid;
 
 /* This is true for configurations that may follow through execl() and
-   similar functions.  At present this is only true for HP-UX native.  */
+   similar functions.  */
 
 #ifndef MAY_FOLLOW_EXEC
-#define MAY_FOLLOW_EXEC (0)
+#define MAY_FOLLOW_EXEC (1)
 #endif
 
 static int may_follow_exec = MAY_FOLLOW_EXEC;
@@ -375,6 +376,37 @@ follow_inferior_reset_breakpoints (void)
   insert_breakpoints ();
 }
 
+static void
+follow_exec_restore_execfile (void *filename_new_untyped)
+{
+  char *filename_new = filename_new_untyped;
+
+  /* filename_new == NULL is not expected.  */
+  if (filename_new == NULL && exec_bfd != NULL)
+    exec_file_clear (0);
+  /* exec_bfd == NULL is not expected.  */
+  if (filename_new != NULL && 
+      (exec_bfd == NULL || strcmp (get_exec_file (0), filename_new)))
+    exec_file_attach (filename_new, 0);
+
+  free (filename_new);
+}
+
+static void
+follow_exec_restore_symfile (void *filename_new_untyped)
+{
+  char *filename_new = filename_new_untyped;
+
+  /* symfile_objfile == NULL is not expected.  */
+  if (filename_new == NULL && symfile_objfile != NULL)
+    symbol_file_clear (0);
+  if (filename_new != NULL && (symfile_objfile == NULL
+      || strcmp (symfile_objfile->name, filename_new)))
+    symbol_file_add_main (filename_new, 0);
+
+  free (filename_new);
+}
+
 /* EXECD_PATHNAME is assumed to be non-NULL. */
 
 static void
@@ -382,6 +414,7 @@ follow_exec (int pid, char *execd_pathna
 {
   int saved_pid = pid;
   struct target_ops *tgt;
+  struct objfile *objfile, *objfile_temp;
 
   if (!may_follow_exec)
     return;
@@ -427,6 +460,30 @@ follow_exec (int pid, char *execd_pathna
     error (_("Could find run target to save before following exec"));
 
   gdb_flush (gdb_stdout);
+
+  /* During the common "run" bare command we should run again the original
+   * program spawning us.  Stacking ordering is correct this way.  */
+  make_run_cleanup (follow_exec_restore_execfile,
+                    (!exec_bfd ? NULL : xstrdup (exec_bfd->filename)));
+  make_run_cleanup (follow_exec_restore_symfile, (!symfile_objfile ? NULL :
+                    xstrdup (symfile_objfile->name)));
+
+  /* As symbol_file_add_main()->thread_db_new_objfile()->check_for_thread_db()
+   * would fine already loaded libpthread.so while the threading structures
+   * would not be yet initialized for this early inferior.
+   * Call before target_mourn_inferior() as it will breakpoint_re_set().  */
+#ifdef CLEAR_SOLIB
+  CLEAR_SOLIB ();
+#else
+  clear_solib ();
+#endif
+  /* Do not: symbol_file_clear()->clear_symtab_users()->breakpoint_re_set().  */
+  ALL_OBJFILES_SAFE (objfile, objfile_temp)
+  {
+    free_objfile (objfile);
+  }
+  symfile_objfile = NULL;
+
   target_mourn_inferior ();
   inferior_ptid = pid_to_ptid (saved_pid);
   /* Because mourn_inferior resets inferior_ptid. */
diff -rup gdb-6.5-orig/gdb/linux-thread-db.c gdb-6.5-follow_exec/gdb/linux-thread-db.c
--- gdb-6.5-orig/gdb/linux-thread-db.c	2006-07-28 23:30:22.000000000 +0200
+++ gdb-6.5-follow_exec/gdb/linux-thread-db.c	2006-07-29 11:26:32.000000000 +0200
@@ -939,6 +939,10 @@ thread_db_wait (ptid_t ptid, struct targ
       || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
     return pid_to_ptid (-1);
 
+  /* Threading structures got reset.  Return as nonthreaded.  */
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    return pid_to_ptid (GET_PID (ptid));
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && (ourstatus->value.sig == TARGET_SIGNAL_TRAP
           || ourstatus->value.sig == TARGET_SIGNAL_ILL))
@@ -1106,6 +1110,9 @@ thread_db_mourn_inferior (void)
      the inferior, so that we don't try to uninsert them.  */
   remove_thread_event_breakpoints ();
 
+  /* Destroy thread info; it's no longer valid.  */
+  init_thread_list ();
+
   /* Detach thread_db target ops.  */
   unpush_target (&thread_db_ops);
   using_thread_db = 0;
diff -rup gdb-6.5-orig/gdb/testsuite/gdb.base/foll-exec.exp gdb-6.5-follow_exec/gdb/testsuite/gdb.base/foll-exec.exp
--- gdb-6.5-orig/gdb/testsuite/gdb.base/foll-exec.exp	2001-03-06 09:21:50.000000000 +0100
+++ gdb-6.5-follow_exec/gdb/testsuite/gdb.base/foll-exec.exp	2006-07-29 11:26:32.000000000 +0200
@@ -45,12 +45,6 @@ if  { [gdb_compile "${srcdir}/${subdir}/
 }
 
 
-# Until "catch exec" is implemented on other targets...
-#
-if ![istarget "hppa*-hp-hpux*"] then {
-    continue
-}
-
 proc zap_session {} {
    global gdb_prompt
    global binfile
@@ -212,7 +206,9 @@ proc do_exec_tests {} {
    setup_xfail hppa2.0w-hp-hpux* CLLbs16760
    send_gdb "continue\n"
    gdb_expect {
-     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\
+     # It is OS dependent and no symbols may be found, GNU/Linux has "_start"
+     # while HP-UX has " in .START..*$gdb_prompt" etc.
+     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .*$gdb_prompt $"\
                      {pass "hit catch exec"}
      -re "$gdb_prompt $" {fail "hit catch exec"}
      timeout         {fail "(timeout) hit catch exec"}

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

* Re: [patch] Linux MAY_FOLLOW_EXEC #2  [Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)]
  2006-07-29 18:54             ` [patch] Linux MAY_FOLLOW_EXEC #2 [Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)] Jan Kratochvil
@ 2006-07-31 20:39               ` Mark Kettenis
  2006-08-05 16:43                 ` [patch] Linux MAY_FOLLOW_EXEC #2 Jan Kratochvil
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Kettenis @ 2006-07-31 20:39 UTC (permalink / raw)
  To: jan.kratochvil; +Cc: drow, gdb-patches

> Date: Sat, 29 Jul 2006 20:53:17 +0200
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> 
> That waitpid(3) WNOHANG smells there for me but it does not hurt the
> testsuite.  Should I investigate it more?

That WNOHANG is wrong; inf_ptrace_mourn_inferior() is supposed to be
called when the inferior died.  We must call waitpid(2) to make sure
we don't leave behind a zombie.  Unfortunately there is some sort of
race and we have to do a blocking wait at this stage, otherwise the
rotting corpse might still escape us.

Mark


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

* Re: [patch] Linux MAY_FOLLOW_EXEC #2
  2006-07-31 20:39               ` Mark Kettenis
@ 2006-08-05 16:43                 ` Jan Kratochvil
  2006-08-08 16:01                   ` Daniel Jacobowitz
  0 siblings, 1 reply; 11+ messages in thread
From: Jan Kratochvil @ 2006-08-05 16:43 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: drow, gdb-patches

[-- Attachment #1: Type: text/plain, Size: 810 bytes --]

Hi Mark,

On Mon, 31 Jul 2006 22:38:43 +0200, Mark Kettenis wrote:
...
> That WNOHANG is wrong;

In fact yes, the patch is more correct without that WNOHANG hack there.


2006-07-29  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* inf-ptrace.c (inf_ptrace_mourn_inferior): waitpid(2) only if there
	is valid inferior_ptid to wait for.
	* linux-fork.c (linux_fork_mourn_inferior): Ditto.
	* infrun.c (follow_exec): Unconditionally enabled by MAY_FOLLOW_EXEC.
	Provide restoration of exec_bfd and symfile_objfile for any new "run".
	* linux-thread-db.c (thread_db_wait): Handle TARGET_WAITKIND_EXECD.
	* linux-thread-db.c (thread_db_mourn_inferior): Turn off threading.
	* foll-exec.exp: Uncoditionally enabled for all platforms.
	Relaxed regex to apply besides HP-UX also for GNU/Linux backtrace.


Thanks,
Jan

[-- Attachment #2: gdb-6.5-follow-exec-v2.patch --]
[-- Type: text/plain, Size: 7255 bytes --]

Index: inf-ptrace.c
===================================================================
RCS file: /cvs/src/src/gdb/inf-ptrace.c,v
retrieving revision 1.32
diff -u -p -r1.32 inf-ptrace.c
--- inf-ptrace.c	24 Jan 2006 22:34:34 -0000	1.32
+++ inf-ptrace.c	5 Aug 2006 15:49:22 -0000
@@ -167,7 +167,8 @@ inf_ptrace_mourn_inferior (void)
      Do not check whether this succeeds though, since we may be
      dealing with a process that we attached to.  Such a process will
      only report its exit status to its original parent.  */
-  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+  if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
+    waitpid (ptid_get_pid (inferior_ptid), &status, 0);
 
   unpush_target (ptrace_ops_hack);
   generic_mourn_inferior ();
Index: infrun.c
===================================================================
RCS file: /cvs/src/src/gdb/infrun.c,v
retrieving revision 1.213
diff -u -p -r1.213 infrun.c
--- infrun.c	22 Jul 2006 14:48:03 -0000	1.213
+++ infrun.c	5 Aug 2006 15:49:28 -0000
@@ -47,6 +47,7 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "objfiles.h"
 
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
@@ -109,10 +110,10 @@ int sync_execution = 0;
 static ptid_t previous_inferior_ptid;
 
 /* This is true for configurations that may follow through execl() and
-   similar functions.  At present this is only true for HP-UX native.  */
+   similar functions.  */
 
 #ifndef MAY_FOLLOW_EXEC
-#define MAY_FOLLOW_EXEC (0)
+#define MAY_FOLLOW_EXEC (1)
 #endif
 
 static int may_follow_exec = MAY_FOLLOW_EXEC;
@@ -375,6 +376,37 @@ follow_inferior_reset_breakpoints (void)
   insert_breakpoints ();
 }
 
+static void
+follow_exec_restore_execfile (void *filename_new_untyped)
+{
+  char *filename_new = filename_new_untyped;
+
+  /* filename_new == NULL is not expected.  */
+  if (filename_new == NULL && exec_bfd != NULL)
+    exec_file_clear (0);
+  /* exec_bfd == NULL is not expected.  */
+  if (filename_new != NULL && 
+      (exec_bfd == NULL || strcmp (get_exec_file (0), filename_new)))
+    exec_file_attach (filename_new, 0);
+
+  free (filename_new);
+}
+
+static void
+follow_exec_restore_symfile (void *filename_new_untyped)
+{
+  char *filename_new = filename_new_untyped;
+
+  /* symfile_objfile == NULL is not expected.  */
+  if (filename_new == NULL && symfile_objfile != NULL)
+    symbol_file_clear (0);
+  if (filename_new != NULL && (symfile_objfile == NULL
+      || strcmp (symfile_objfile->name, filename_new)))
+    symbol_file_add_main (filename_new, 0);
+
+  free (filename_new);
+}
+
 /* EXECD_PATHNAME is assumed to be non-NULL. */
 
 static void
@@ -382,6 +414,7 @@ follow_exec (int pid, char *execd_pathna
 {
   int saved_pid = pid;
   struct target_ops *tgt;
+  struct objfile *objfile, *objfile_temp;
 
   if (!may_follow_exec)
     return;
@@ -427,6 +460,32 @@ follow_exec (int pid, char *execd_pathna
     error (_("Could find run target to save before following exec"));
 
   gdb_flush (gdb_stdout);
+
+  /* During the common "run" bare command we should run again the original
+   * program spawning us.  Stacking ordering is correct this way.  */
+  make_run_cleanup (follow_exec_restore_execfile,
+                    (!exec_bfd ? NULL : xstrdup (exec_bfd->filename)));
+  make_run_cleanup (follow_exec_restore_symfile, (!symfile_objfile ? NULL :
+                    xstrdup (symfile_objfile->name)));
+
+  /* As symbol_file_add_main()->thread_db_new_objfile()->check_for_thread_db()
+   * would fine already loaded libpthread.so while the threading structures
+   * would not be yet initialized for this early inferior.
+   * Call before target_mourn_inferior() as it will breakpoint_re_set().  */
+#ifdef CLEAR_SOLIB
+  CLEAR_SOLIB ();
+#else
+  clear_solib ();
+#endif
+  /* Do not: symbol_file_clear()->clear_symtab_users()->breakpoint_re_set().  */
+  ALL_OBJFILES_SAFE (objfile, objfile_temp)
+  {
+    free_objfile (objfile);
+  }
+  symfile_objfile = NULL;
+
+  /* Avoid stucked waitpid(2) as PID inferior_ptid is still running.  */
+  inferior_ptid = null_ptid;
   target_mourn_inferior ();
   inferior_ptid = pid_to_ptid (saved_pid);
   /* Because mourn_inferior resets inferior_ptid. */
Index: linux-fork.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-fork.c,v
retrieving revision 1.7
diff -u -p -r1.7 linux-fork.c
--- linux-fork.c	27 Apr 2006 23:03:41 -0000	1.7
+++ linux-fork.c	5 Aug 2006 15:49:45 -0000
@@ -366,7 +366,8 @@ linux_fork_mourn_inferior (void)
      only report its exit status to its original parent.  */
   int status;
 
-  waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+  if (! ptid_equal (inferior_ptid, null_ptid) && target_has_execution)
+    waitpid (ptid_get_pid (inferior_ptid), &status, 0);
 
   /* OK, presumably inferior_ptid is the one who has exited.
      We need to delete that one from the fork_list, and switch
Index: linux-thread-db.c
===================================================================
RCS file: /cvs/src/src/gdb/linux-thread-db.c,v
retrieving revision 1.19
diff -u -p -r1.19 linux-thread-db.c
--- linux-thread-db.c	2 Aug 2006 10:24:00 -0000	1.19
+++ linux-thread-db.c	5 Aug 2006 15:50:49 -0000
@@ -884,6 +884,10 @@ thread_db_wait (ptid_t ptid, struct targ
       return pid_to_ptid (GET_PID (ptid));
     }
 
+  /* Threading structures got reset.  Return as nonthreaded.  */
+  if (ourstatus->kind == TARGET_WAITKIND_EXECD)
+    return pid_to_ptid (GET_PID (ptid));
+
   if (ourstatus->kind == TARGET_WAITKIND_STOPPED
       && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
     /* Check for a thread event.  */
@@ -975,6 +979,9 @@ thread_db_mourn_inferior (void)
      the inferior, so that we don't try to uninsert them.  */
   remove_thread_event_breakpoints ();
 
+  /* Destroy thread info; it's no longer valid.  */
+  init_thread_list ();
+
   /* Detach thread_db target ops.  */
   unpush_target (&thread_db_ops);
   using_thread_db = 0;
Index: testsuite/gdb.base/foll-exec.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.base/foll-exec.exp,v
retrieving revision 1.2
diff -u -p -r1.2 foll-exec.exp
--- testsuite/gdb.base/foll-exec.exp	6 Mar 2001 08:21:50 -0000	1.2
+++ testsuite/gdb.base/foll-exec.exp	5 Aug 2006 15:50:50 -0000
@@ -45,12 +45,6 @@ if  { [gdb_compile "${srcdir}/${subdir}/
 }
 
 
-# Until "catch exec" is implemented on other targets...
-#
-if ![istarget "hppa*-hp-hpux*"] then {
-    continue
-}
-
 proc zap_session {} {
    global gdb_prompt
    global binfile
@@ -212,7 +206,9 @@ proc do_exec_tests {} {
    setup_xfail hppa2.0w-hp-hpux* CLLbs16760
    send_gdb "continue\n"
    gdb_expect {
-     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .START..*$gdb_prompt $"\
+     # It is OS dependent and no symbols may be found, GNU/Linux has "_start"
+     # while HP-UX has " in .START..*$gdb_prompt" etc.
+     -re ".*Executing new program:.*${testfile2}.*Catchpoint .*(exec\'d .*${testfile2}).*in .*$gdb_prompt $"\
                      {pass "hit catch exec"}
      -re "$gdb_prompt $" {fail "hit catch exec"}
      timeout         {fail "(timeout) hit catch exec"}

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

* Re: [patch] Linux MAY_FOLLOW_EXEC #2
  2006-08-05 16:43                 ` [patch] Linux MAY_FOLLOW_EXEC #2 Jan Kratochvil
@ 2006-08-08 16:01                   ` Daniel Jacobowitz
  0 siblings, 0 replies; 11+ messages in thread
From: Daniel Jacobowitz @ 2006-08-08 16:01 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Mark Kettenis, gdb-patches

On Sat, Aug 05, 2006 at 06:41:44PM +0200, Jan Kratochvil wrote:
> Hi Mark,
> 
> On Mon, 31 Jul 2006 22:38:43 +0200, Mark Kettenis wrote:
> ...
> > That WNOHANG is wrong;
> 
> In fact yes, the patch is more correct without that WNOHANG hack there.
> 
> 
> 2006-07-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	* inf-ptrace.c (inf_ptrace_mourn_inferior): waitpid(2) only if there
> 	is valid inferior_ptid to wait for.
> 	* linux-fork.c (linux_fork_mourn_inferior): Ditto.
> 	* infrun.c (follow_exec): Unconditionally enabled by MAY_FOLLOW_EXEC.
> 	Provide restoration of exec_bfd and symfile_objfile for any new "run".
> 	* linux-thread-db.c (thread_db_wait): Handle TARGET_WAITKIND_EXECD.
> 	* linux-thread-db.c (thread_db_mourn_inferior): Turn off threading.
> 	* foll-exec.exp: Uncoditionally enabled for all platforms.
> 	Relaxed regex to apply besides HP-UX also for GNU/Linux backtrace.

Sorry, but I can't approve this patch.  I think someone needs to
discuss the concept and interface on gdb@ first.

You're using make_run_cleanup to restore the inferior file.  This means
it happens before "run".  Any time we choose to change the file
silently will be surprising (especially to front ends like Eclipse) but
that time will be pretty surprising to the user too:

... info files shows first prog
(gdb) catch exec
(gdb) run
... info files shows second prog
(gdb) continue
... exits.
... info files shows second prog
(gdb) run
... starts first prog!

I also think that changing inferior_ptid before mourning is pretty
strange.  The whole way follow_exec works is a hack and not
particularly well defined.

This is a hard problem to solve; I think a half-finished solution would
be worse than leaving it unsolved.

-- 
Daniel Jacobowitz
CodeSourcery


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

end of thread, other threads:[~2006-08-08 16:01 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-14 10:55 RFC: Fix crash on i386 (%gs-)threaded programs using execve(2) Jan Kratochvil
2006-06-14 14:25 ` Daniel Jacobowitz
2006-06-15 20:36   ` Jan Kratochvil
2006-07-21 18:16     ` Jan Kratochvil
2006-07-21 18:44       ` Daniel Jacobowitz
2006-07-22 12:31         ` Jan Kratochvil
2006-07-24 19:03           ` Daniel Jacobowitz
2006-07-29 18:54             ` [patch] Linux MAY_FOLLOW_EXEC #2 [Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)] Jan Kratochvil
2006-07-31 20:39               ` Mark Kettenis
2006-08-05 16:43                 ` [patch] Linux MAY_FOLLOW_EXEC #2 Jan Kratochvil
2006-08-08 16:01                   ` Daniel Jacobowitz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox