strace/backport-0004-Factor-out-interrupt_or_stop-from-detach.patch

128 lines
3.5 KiB
Diff
Raw Permalink Normal View History

From 4c4c339585b523167e336d9b379fe4c00dc94dca Mon Sep 17 00:00:00 2001
From: "Dmitry V. Levin" <ldv@strace.io>
Date: Sun, 26 Nov 2023 08:00:00 +0000
Subject: [PATCH] Factor out interrupt_or_stop() from detach()
* src/strace.c (interrupt_or_stop): New function.
(detach): Use it.
Reference: https://github.com/strace/strace/commit/4c4c339585b523167e336d9b379fe4c00dc94dca
Conflict: NA
---
src/strace.c | 49 ++++++++++++++++++++++++++++---------------------
1 file changed, 28 insertions(+), 21 deletions(-)
diff --git a/src/strace.c b/src/strace.c
index 351842792..385cbaa72 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -1158,17 +1158,10 @@ droptcb_verbose(struct tcb *tcp)
droptcb(tcp);
}
-/* Detach traced process.
- * Never call DETACH twice on the same process as both unattached and
- * attached-unstopped processes give the same ESRCH. For unattached process we
- * would SIGSTOP it and wait for its SIGSTOP notification forever.
- */
-static void
-detach(struct tcb *tcp)
+/* Returns true when the tracee has to be waited for. */
+static bool
+interrupt_or_stop(struct tcb *tcp)
{
- int error;
- int status;
-
/*
* Linux wrongly insists the child be stopped
* before detaching. Arghh. We go through hoops
@@ -1176,24 +1169,24 @@ detach(struct tcb *tcp)
*/
if (!(tcp->flags & TCB_ATTACHED))
- goto drop;
+ return false;
/* We attached but possibly didn't see the expected SIGSTOP.
* We must catch exactly one as otherwise the detached process
* would be left stopped (process state T).
*/
if (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)
- goto wait_loop;
+ return true;
- error = ptrace(PTRACE_DETACH, tcp->pid, 0, 0);
+ int error = ptrace(PTRACE_DETACH, tcp->pid, 0, 0);
if (!error) {
/* On a clear day, you can see forever. */
- goto drop;
+ return false;
}
if (errno != ESRCH) {
/* Shouldn't happen. */
perror_func_msg("ptrace(PTRACE_DETACH,%u)", tcp->pid);
- goto drop;
+ return false;
}
/* ESRCH: process is either not stopped or doesn't exist. */
if (my_tkill(tcp->pid, 0) < 0) {
@@ -1201,7 +1194,7 @@ detach(struct tcb *tcp)
/* Shouldn't happen. */
perror_func_msg("tkill(%u,0)", tcp->pid);
/* else: process doesn't exist. */
- goto drop;
+ return false;
}
/* Process is not stopped, need to stop it. */
if (use_seize) {
@@ -1213,26 +1206,40 @@ detach(struct tcb *tcp)
*/
error = ptrace(PTRACE_INTERRUPT, tcp->pid, 0, 0);
if (!error)
- goto wait_loop;
+ return true;
if (errno != ESRCH)
perror_func_msg("ptrace(PTRACE_INTERRUPT,%u)", tcp->pid);
} else {
error = my_tkill(tcp->pid, SIGSTOP);
if (!error)
- goto wait_loop;
+ return true;
if (errno != ESRCH)
perror_func_msg("tkill(%u,SIGSTOP)", tcp->pid);
}
+
/* Either process doesn't exist, or some weird error. */
- goto drop;
+ return false;
+}
- wait_loop:
- /* We end up here in three cases:
+/* Detach traced process.
+ * Never call DETACH twice on the same process as both unattached and
+ * attached-unstopped processes give the same ESRCH. For unattached process we
+ * would SIGSTOP it and wait for its SIGSTOP notification forever.
+ */
+static void
+detach(struct tcb *tcp)
+{
+ if (!interrupt_or_stop(tcp))
+ goto drop;
+
+ /*
+ * We end up here in three cases:
* 1. We sent PTRACE_INTERRUPT (use_seize case)
* 2. We sent SIGSTOP (!use_seize)
* 3. Attach SIGSTOP was already pending (TCB_IGNORE_ONE_SIGSTOP set)
*/
for (;;) {
+ int status;
unsigned int sig;
if (waitpid(tcp->pid, &status, __WALL) < 0) {
if (errno == EINTR)
--
2.33.0