This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: RFC: Fix crash on i386 (%gs-)threaded programs using execve(2)


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
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"}
--- -	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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]