Fix race conditions in pldd that may leave the process stopped after detaching
authorAndreas Schwab <schwab@suse.de>
Tue, 30 Jul 2013 09:58:45 +0000 (11:58 +0200)
committerAndreas Schwab <schwab@suse.de>
Tue, 25 Feb 2014 08:29:34 +0000 (09:29 +0100)
Fixes bug 15804

ChangeLog
NEWS
elf/pldd.c

index a9fe7a5..9f28d70 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2014-02-24  Andreas Schwab  <schwab@suse.de>
+
+       [BZ #15804]
+       * elf/pldd.c (wait_for_ptrace_stop): New function.
+       (main): Call it after attaching.
+
 2014-02-22  Roland McGrath  <roland@hack.frob.com>
 
        * Makerules ($(common-objpfx)Versions.v.i): No longer depend
diff --git a/NEWS b/NEWS
index dc5f380..3698c40 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,7 +9,7 @@ Version 2.20
 
 * The following bugs are resolved with this release:
 
-  15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611.
+  15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611.
 
 * The am33 port, which had not worked for several years, has been removed
   from ports.
index 684aff4..75f7812 100644 (file)
@@ -34,6 +34,7 @@
 #include <unistd.h>
 #include <sys/ptrace.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 
 #include <ldsodefs.h>
 #include <version.h>
@@ -82,6 +83,7 @@ static char *exe;
 
 /* Local functions.  */
 static int get_process_info (int dfd, long int pid);
+static void wait_for_ptrace_stop (long int pid);
 
 
 int
@@ -170,6 +172,8 @@ main (int argc, char *argv[])
                 tid);
        }
 
+      wait_for_ptrace_stop (tid);
+
       struct thread_list *newp = alloca (sizeof (*newp));
       newp->tid = tid;
       newp->next = thread_list;
@@ -194,6 +198,27 @@ main (int argc, char *argv[])
 }
 
 
+/* Wait for PID to enter ptrace-stop state after being attached.  */
+static void
+wait_for_ptrace_stop (long int pid)
+{
+  int status;
+
+  /* While waiting for SIGSTOP being delivered to the tracee we have to
+     reinject any other pending signal.  Ignore all other errors.  */
+  while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status))
+    {
+      /* The STOP signal should not be delivered to the tracee.  */
+      if (WSTOPSIG (status) == SIGSTOP)
+       return;
+      if (ptrace (PTRACE_CONT, pid, NULL,
+                 (void *) (uintptr_t) WSTOPSIG (status)))
+       /* The only possible error is that the process died.  */
+       return;
+    }
+}
+
+
 /* Handle program arguments.  */
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)