From b04acb2651e0aaf615de50e9138cddfd5c24021f Mon Sep 17 00:00:00 2001 From: Andreas Schwab Date: Tue, 30 Jul 2013 11:58:45 +0200 Subject: [PATCH] Fix race conditions in pldd that may leave the process stopped after detaching Fixes bug 15804 --- ChangeLog | 6 ++++++ NEWS | 2 +- elf/pldd.c | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a9fe7a5cbc..9f28d70e19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-02-24 Andreas Schwab + + [BZ #15804] + * elf/pldd.c (wait_for_ptrace_stop): New function. + (main): Call it after attaching. + 2014-02-22 Roland McGrath * 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 #include #include +#include #include #include @@ -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) -- 2.11.4.GIT