summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2013-07-30 11:58:45 +0200
committerAndreas Schwab <schwab@suse.de>2014-02-25 09:29:34 +0100
commitb04acb2651e0aaf615de50e9138cddfd5c24021f (patch)
tree4908e5a456a4316f468ac3bc8cce6437eb874250
parentd4ec6ae19e3290abbb3cfff70a8dd6018ecb6e2e (diff)
Fix race conditions in pldd that may leave the process stopped after detaching
Fixes bug 15804
-rw-r--r--ChangeLog6
-rw-r--r--NEWS2
-rw-r--r--elf/pldd.c25
3 files changed, 32 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index a9fe7a5cbc..9f28d70e19 100644
--- 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 dc5f380a1d..3698c404f0 100644
--- 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.
diff --git a/elf/pldd.c b/elf/pldd.c
index 684aff4dba..75f78120df 100644
--- a/elf/pldd.c
+++ b/elf/pldd.c
@@ -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)