|
|
147e83 |
commit b04acb2651e0aaf615de50e9138cddfd5c24021f
|
|
|
147e83 |
Author: Andreas Schwab <schwab@suse.de>
|
|
|
147e83 |
Date: Tue Jul 30 11:58:45 2013 +0200
|
|
|
147e83 |
|
|
|
147e83 |
Fix race conditions in pldd that may leave the process stopped after detaching
|
|
|
147e83 |
|
|
|
147e83 |
Fixes bug 15804
|
|
|
147e83 |
|
|
|
147e83 |
diff --git a/elf/pldd.c b/elf/pldd.c
|
|
|
147e83 |
index 684aff4..75f7812 100644
|
|
|
147e83 |
--- a/elf/pldd.c
|
|
|
147e83 |
+++ b/elf/pldd.c
|
|
|
147e83 |
@@ -34,6 +34,7 @@
|
|
|
147e83 |
#include <unistd.h>
|
|
|
147e83 |
#include <sys/ptrace.h>
|
|
|
147e83 |
#include <sys/stat.h>
|
|
|
147e83 |
+#include <sys/wait.h>
|
|
|
147e83 |
|
|
|
147e83 |
#include <ldsodefs.h>
|
|
|
147e83 |
#include <version.h>
|
|
|
147e83 |
@@ -82,6 +83,7 @@ static char *exe;
|
|
|
147e83 |
|
|
|
147e83 |
/* Local functions. */
|
|
|
147e83 |
static int get_process_info (int dfd, long int pid);
|
|
|
147e83 |
+static void wait_for_ptrace_stop (long int pid);
|
|
|
147e83 |
|
|
|
147e83 |
|
|
|
147e83 |
int
|
|
|
147e83 |
@@ -170,6 +172,8 @@ main (int argc, char *argv[])
|
|
|
147e83 |
tid);
|
|
|
147e83 |
}
|
|
|
147e83 |
|
|
|
147e83 |
+ wait_for_ptrace_stop (tid);
|
|
|
147e83 |
+
|
|
|
147e83 |
struct thread_list *newp = alloca (sizeof (*newp));
|
|
|
147e83 |
newp->tid = tid;
|
|
|
147e83 |
newp->next = thread_list;
|
|
|
147e83 |
@@ -194,6 +198,27 @@ main (int argc, char *argv[])
|
|
|
147e83 |
}
|
|
|
147e83 |
|
|
|
147e83 |
|
|
|
147e83 |
+/* Wait for PID to enter ptrace-stop state after being attached. */
|
|
|
147e83 |
+static void
|
|
|
147e83 |
+wait_for_ptrace_stop (long int pid)
|
|
|
147e83 |
+{
|
|
|
147e83 |
+ int status;
|
|
|
147e83 |
+
|
|
|
147e83 |
+ /* While waiting for SIGSTOP being delivered to the tracee we have to
|
|
|
147e83 |
+ reinject any other pending signal. Ignore all other errors. */
|
|
|
147e83 |
+ while (waitpid (pid, &status, __WALL) == pid && WIFSTOPPED (status))
|
|
|
147e83 |
+ {
|
|
|
147e83 |
+ /* The STOP signal should not be delivered to the tracee. */
|
|
|
147e83 |
+ if (WSTOPSIG (status) == SIGSTOP)
|
|
|
147e83 |
+ return;
|
|
|
147e83 |
+ if (ptrace (PTRACE_CONT, pid, NULL,
|
|
|
147e83 |
+ (void *) (uintptr_t) WSTOPSIG (status)))
|
|
|
147e83 |
+ /* The only possible error is that the process died. */
|
|
|
147e83 |
+ return;
|
|
|
147e83 |
+ }
|
|
|
147e83 |
+}
|
|
|
147e83 |
+
|
|
|
147e83 |
+
|
|
|
147e83 |
/* Handle program arguments. */
|
|
|
147e83 |
static error_t
|
|
|
147e83 |
parse_opt (int key, char *arg, struct argp_state *state)
|