|
|
d4bfbf |
From c527f21b7528e14b13d2be13acf5c42359e94021 Mon Sep 17 00:00:00 2001
|
|
|
d4bfbf |
From: Eugene Syromyatnikov <evgsyr@gmail.com>
|
|
|
d4bfbf |
Date: Wed, 8 Aug 2018 21:41:39 +0200
|
|
|
d4bfbf |
Subject: [PATCH 3/3] Implement queueing of threads before dispatching them
|
|
|
d4bfbf |
|
|
|
d4bfbf |
It is possible that some tracees call a lot of cheap syscalls too fast,
|
|
|
d4bfbf |
and that can lead to starvation to the point some tracees are not served
|
|
|
d4bfbf |
for indefinite amount of time. In order to solve that unfairness, try
|
|
|
d4bfbf |
to collect all the pending tracees first along with the relevant
|
|
|
d4bfbf |
information and only then dispatch the events.
|
|
|
d4bfbf |
|
|
|
d4bfbf |
* defs.h: Include "list.h".
|
|
|
d4bfbf |
(struct tcb): Add wait_data_idx and wait_list fields.
|
|
|
d4bfbf |
* strace.c (struct tcb_wait_data): Add "msg" field.
|
|
|
d4bfbf |
(tcb_wait_tab): New static variable.
|
|
|
d4bfbf |
(expand_tcbtab): Resize tcb_wait_tab along with tcbtab, provide
|
|
|
d4bfbf |
an additional slot for extra event.
|
|
|
d4bfbf |
(droptcb): Remove tcp from wait_list.
|
|
|
d4bfbf |
(maybe_switch_tcbs): Get old pid from
|
|
|
d4bfbf |
tcb_wait_tab[tcp->wait_data_idx].msg.
|
|
|
d4bfbf |
(next_event): Add pending_tcps, extra_tcp, wait_nohang, elem, and
|
|
|
d4bfbf |
wait_tab_pos variables; check for elements in pending_tcps and skip
|
|
|
d4bfbf |
waiting if the list is not empty; check for extra_tcp and skip waiting
|
|
|
d4bfbf |
along with swapping wait_data_idx with wait_extra_data_idx;
|
|
|
d4bfbf |
after the initial wait, call wait4() in loop with WNOHANG flag set;
|
|
|
d4bfbf |
fetch siginfo on signal and eventmsg on PTRACE_EVENT_EXEC;
|
|
|
d4bfbf |
return the first tcp in pending_tcps list.
|
|
|
d4bfbf |
* tests/Makefile.am (XFAIL_TEST): Remove looping_threads.test.
|
|
|
d4bfbf |
|
|
|
d4bfbf |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=478419
|
|
|
d4bfbf |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=526740
|
|
|
d4bfbf |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=851457
|
|
|
d4bfbf |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1609318
|
|
|
d4bfbf |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1610774
|
|
|
d4bfbf |
Co-Authored-by: Dmitry V. Levin <ldv@altlinux.org>
|
|
|
d4bfbf |
Co-Authored-by: Denys Vlasenko <dvlasenk@redhat.com>
|
|
|
d4bfbf |
Co-Authored-by: Andreas Schwab <aschwab@redhat.com>
|
|
|
d4bfbf |
Co-Authored-by: Jeff Law <law@redhat.com>
|
|
|
d4bfbf |
Co-Authored-by: DJ Delorie <dj@redhat.com>
|
|
|
d4bfbf |
---
|
|
|
d4bfbf |
defs.h | 10 ++
|
|
|
d4bfbf |
strace.c | 321 ++++++++++++++++++++++++++++++++++--------------------
|
|
|
d4bfbf |
tests/Makefile.am | 3 +-
|
|
|
d4bfbf |
3 files changed, 212 insertions(+), 122 deletions(-)
|
|
|
d4bfbf |
|
|
|
d4bfbf |
Index: strace-4.24/defs.h
|
|
|
d4bfbf |
===================================================================
|
|
|
d4bfbf |
--- strace-4.24.orig/defs.h 2018-09-12 23:52:48.978021943 +0200
|
|
|
d4bfbf |
+++ strace-4.24/defs.h 2018-09-12 23:53:35.764480931 +0200
|
|
|
d4bfbf |
@@ -57,6 +57,7 @@
|
|
|
d4bfbf |
#include "error_prints.h"
|
|
|
d4bfbf |
#include "gcc_compat.h"
|
|
|
d4bfbf |
#include "kernel_types.h"
|
|
|
d4bfbf |
+#include "list.h"
|
|
|
d4bfbf |
#include "macros.h"
|
|
|
d4bfbf |
#include "mpers_type.h"
|
|
|
d4bfbf |
#include "string_to_uint.h"
|
|
|
d4bfbf |
@@ -236,6 +237,15 @@
|
|
|
d4bfbf |
|
|
|
d4bfbf |
struct mmap_cache_t *mmap_cache;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * Data that is stored during process wait traversal.
|
|
|
d4bfbf |
+ * We use indices as the actual data is stored in an array
|
|
|
d4bfbf |
+ * that is realloc'ed in runtime.
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ size_t wait_data_idx;
|
|
|
d4bfbf |
+ struct list_item wait_list;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
#ifdef HAVE_LINUX_KVM_H
|
|
|
d4bfbf |
struct vcpu_info *vcpu_info_list;
|
|
|
d4bfbf |
#endif
|
|
|
d4bfbf |
Index: strace-4.24/strace.c
|
|
|
d4bfbf |
===================================================================
|
|
|
d4bfbf |
--- strace-4.24.orig/strace.c 2018-09-12 23:53:30.371543291 +0200
|
|
|
d4bfbf |
+++ strace-4.24/strace.c 2018-09-12 23:53:35.765480919 +0200
|
|
|
d4bfbf |
@@ -161,10 +161,17 @@
|
|
|
d4bfbf |
struct tcb_wait_data {
|
|
|
d4bfbf |
enum trace_event te; /**< Event passed to dispatch_event() */
|
|
|
d4bfbf |
int status; /**< status, returned by wait4() */
|
|
|
d4bfbf |
+ unsigned long msg; /**< Value returned by PTRACE_GETEVENTMSG */
|
|
|
d4bfbf |
siginfo_t si; /**< siginfo, returned by PTRACE_GETSIGINFO */
|
|
|
d4bfbf |
};
|
|
|
d4bfbf |
|
|
|
d4bfbf |
static struct tcb **tcbtab;
|
|
|
d4bfbf |
+/*
|
|
|
d4bfbf |
+ * Since the queueing of tracees stops as soon as wait4() returns EAGAIN,
|
|
|
d4bfbf |
+ * or at least two events for a single tracee, tab_wait_tab size shouldn't
|
|
|
d4bfbf |
+ * exceed tcbtabsize + 1.
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+static struct tcb_wait_data *tcb_wait_tab;
|
|
|
d4bfbf |
static unsigned int nprocs;
|
|
|
d4bfbf |
static size_t tcbtabsize;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
@@ -750,6 +757,9 @@
|
|
|
d4bfbf |
for (tcb_ptr = tcbtab + old_tcbtabsize;
|
|
|
d4bfbf |
tcb_ptr < tcbtab + tcbtabsize; tcb_ptr++, newtcbs++)
|
|
|
d4bfbf |
*tcb_ptr = newtcbs;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ tcb_wait_tab = xreallocarray(tcb_wait_tab, sizeof(*tcb_wait_tab),
|
|
|
d4bfbf |
+ tcbtabsize + 1);
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
|
|
|
d4bfbf |
static struct tcb *
|
|
|
d4bfbf |
@@ -853,6 +863,8 @@
|
|
|
d4bfbf |
if (printing_tcp == tcp)
|
|
|
d4bfbf |
printing_tcp = NULL;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
+ list_remove(&tcp->wait_list);
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
memset(tcp, 0, sizeof(*tcp));
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
|
|
|
d4bfbf |
@@ -2071,10 +2083,8 @@
|
|
|
d4bfbf |
{
|
|
|
d4bfbf |
FILE *fp;
|
|
|
d4bfbf |
struct tcb *execve_thread;
|
|
|
d4bfbf |
- long old_pid = 0;
|
|
|
d4bfbf |
+ long old_pid = tcb_wait_tab[tcp->wait_data_idx].msg;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &old_pid) < 0)
|
|
|
d4bfbf |
- return tcp;
|
|
|
d4bfbf |
/* Avoid truncation in pid2tcb() param passing */
|
|
|
d4bfbf |
if (old_pid <= 0 || old_pid == pid)
|
|
|
d4bfbf |
return tcp;
|
|
|
d4bfbf |
@@ -2235,17 +2245,27 @@
|
|
|
d4bfbf |
static const struct tcb_wait_data *
|
|
|
d4bfbf |
next_event(void)
|
|
|
d4bfbf |
{
|
|
|
d4bfbf |
- static struct tcb_wait_data wait_data;
|
|
|
d4bfbf |
-
|
|
|
d4bfbf |
- int pid;
|
|
|
d4bfbf |
- int status;
|
|
|
d4bfbf |
- struct tcb *tcp;
|
|
|
d4bfbf |
- struct tcb_wait_data *wd = &wait_data;
|
|
|
d4bfbf |
- struct rusage ru;
|
|
|
d4bfbf |
-
|
|
|
d4bfbf |
if (interrupted)
|
|
|
d4bfbf |
return NULL;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
+ struct tcb *tcp = NULL;
|
|
|
d4bfbf |
+ struct list_item *elem;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ static EMPTY_LIST(pending_tcps);
|
|
|
d4bfbf |
+ if (!list_is_empty(&pending_tcps))
|
|
|
d4bfbf |
+ goto next_event_get_tcp;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ static struct tcb *extra_tcp;
|
|
|
d4bfbf |
+ static size_t wait_extra_data_idx;
|
|
|
d4bfbf |
+ if (extra_tcp) {
|
|
|
d4bfbf |
+ tcp = extra_tcp;
|
|
|
d4bfbf |
+ extra_tcp = NULL;
|
|
|
d4bfbf |
+ tcp->wait_data_idx = wait_extra_data_idx;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ debug_msg("dequeued extra event for pid %u", tcp->pid);
|
|
|
d4bfbf |
+ goto next_event_exit;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
/*
|
|
|
d4bfbf |
* Used to exit simply when nprocs hits zero, but in this testcase:
|
|
|
d4bfbf |
* int main(void) { _exit(!!fork()); }
|
|
|
d4bfbf |
@@ -2287,8 +2307,10 @@
|
|
|
d4bfbf |
* then the system call will be interrupted and
|
|
|
d4bfbf |
* the expiration will be handled by the signal handler.
|
|
|
d4bfbf |
*/
|
|
|
d4bfbf |
- pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
|
|
|
d4bfbf |
- const int wait_errno = errno;
|
|
|
d4bfbf |
+ int status;
|
|
|
d4bfbf |
+ struct rusage ru;
|
|
|
d4bfbf |
+ int pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL));
|
|
|
d4bfbf |
+ int wait_errno = errno;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
/*
|
|
|
d4bfbf |
* The window of opportunity to handle expirations
|
|
|
d4bfbf |
@@ -2304,135 +2326,194 @@
|
|
|
d4bfbf |
return NULL;
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (pid < 0) {
|
|
|
d4bfbf |
- if (wait_errno == EINTR) {
|
|
|
d4bfbf |
- wd->te = TE_NEXT;
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
+ size_t wait_tab_pos = 0;
|
|
|
d4bfbf |
+ bool wait_nohang = false;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ for (;;) {
|
|
|
d4bfbf |
+ struct tcb_wait_data *wd;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (pid < 0) {
|
|
|
d4bfbf |
+ if (wait_errno == EINTR)
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ if (wait_nohang)
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ if (nprocs == 0 && wait_errno == ECHILD)
|
|
|
d4bfbf |
+ return NULL;
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * If nprocs > 0, ECHILD is not expected,
|
|
|
d4bfbf |
+ * treat it as any other error here:
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ errno = wait_errno;
|
|
|
d4bfbf |
+ perror_msg_and_die("wait4(__WALL)");
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
- if (nprocs == 0 && wait_errno == ECHILD)
|
|
|
d4bfbf |
- return NULL;
|
|
|
d4bfbf |
- /*
|
|
|
d4bfbf |
- * If nprocs > 0, ECHILD is not expected,
|
|
|
d4bfbf |
- * treat it as any other error here:
|
|
|
d4bfbf |
- */
|
|
|
d4bfbf |
- errno = wait_errno;
|
|
|
d4bfbf |
- perror_msg_and_die("wait4(__WALL)");
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- wd->status = status;
|
|
|
d4bfbf |
+ if (!pid)
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (pid == popen_pid) {
|
|
|
d4bfbf |
- if (!WIFSTOPPED(status))
|
|
|
d4bfbf |
- popen_pid = 0;
|
|
|
d4bfbf |
- wd->te = TE_NEXT;
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
+ if (pid == popen_pid) {
|
|
|
d4bfbf |
+ if (!WIFSTOPPED(status))
|
|
|
d4bfbf |
+ popen_pid = 0;
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (debug_flag)
|
|
|
d4bfbf |
- print_debug_info(pid, status);
|
|
|
d4bfbf |
+ if (debug_flag)
|
|
|
d4bfbf |
+ print_debug_info(pid, status);
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- /* Look up 'pid' in our table. */
|
|
|
d4bfbf |
- tcp = pid2tcb(pid);
|
|
|
d4bfbf |
+ /* Look up 'pid' in our table. */
|
|
|
d4bfbf |
+ tcp = pid2tcb(pid);
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (!tcp) {
|
|
|
d4bfbf |
- tcp = maybe_allocate_tcb(pid, status);
|
|
|
d4bfbf |
if (!tcp) {
|
|
|
d4bfbf |
- wd->te = TE_NEXT;
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
+ tcp = maybe_allocate_tcb(pid, status);
|
|
|
d4bfbf |
+ if (!tcp)
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- clear_regs(tcp);
|
|
|
d4bfbf |
+ if (cflag) {
|
|
|
d4bfbf |
+ struct timespec stime = {
|
|
|
d4bfbf |
+ .tv_sec = ru.ru_stime.tv_sec,
|
|
|
d4bfbf |
+ .tv_nsec = ru.ru_stime.tv_usec * 1000
|
|
|
d4bfbf |
+ };
|
|
|
d4bfbf |
+ ts_sub(&tcp->dtime, &stime, &tcp->stime);
|
|
|
d4bfbf |
+ tcp->stime = stime;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (wait_tab_pos > tcbtabsize)
|
|
|
d4bfbf |
+ error_func_msg_and_die("Wait data storage overflow "
|
|
|
d4bfbf |
+ "(wait_tab_pos %zu, nprocs %u, "
|
|
|
d4bfbf |
+ "tcbtabsize %zu)", wait_tab_pos,
|
|
|
d4bfbf |
+ nprocs, tcbtabsize);
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ wd = tcb_wait_tab + wait_tab_pos;
|
|
|
d4bfbf |
+ memset(wd, 0, sizeof(*wd));
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (WIFSIGNALED(status)) {
|
|
|
d4bfbf |
+ wd->te = TE_SIGNALLED;
|
|
|
d4bfbf |
+ } else if (WIFEXITED(status)) {
|
|
|
d4bfbf |
+ wd->te = TE_EXITED;
|
|
|
d4bfbf |
+ } else {
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * As WCONTINUED flag has not been specified to wait4,
|
|
|
d4bfbf |
+ * it cannot be WIFCONTINUED(status), so the only case
|
|
|
d4bfbf |
+ * that remains is WIFSTOPPED(status).
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- /* Set current output file */
|
|
|
d4bfbf |
- set_current_tcp(tcp);
|
|
|
d4bfbf |
+ const unsigned int sig = WSTOPSIG(status);
|
|
|
d4bfbf |
+ const unsigned int event = (unsigned int) status >> 16;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (cflag) {
|
|
|
d4bfbf |
- struct timespec stime = {
|
|
|
d4bfbf |
- .tv_sec = ru.ru_stime.tv_sec,
|
|
|
d4bfbf |
- .tv_nsec = ru.ru_stime.tv_usec * 1000
|
|
|
d4bfbf |
- };
|
|
|
d4bfbf |
- ts_sub(&tcp->dtime, &stime, &tcp->stime);
|
|
|
d4bfbf |
- tcp->stime = stime;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
+ switch (event) {
|
|
|
d4bfbf |
+ case 0:
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * Is this post-attach SIGSTOP?
|
|
|
d4bfbf |
+ * Interestingly, the process may stop
|
|
|
d4bfbf |
+ * with STOPSIG equal to some other signal
|
|
|
d4bfbf |
+ * than SIGSTOP if we happened to attach
|
|
|
d4bfbf |
+ * just before the process takes a signal.
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ if (sig == SIGSTOP &&
|
|
|
d4bfbf |
+ (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
|
|
|
d4bfbf |
+ debug_func_msg("ignored SIGSTOP on "
|
|
|
d4bfbf |
+ "pid %d", tcp->pid);
|
|
|
d4bfbf |
+ tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
|
|
|
d4bfbf |
+ wd->te = TE_RESTART;
|
|
|
d4bfbf |
+ } else if (sig == syscall_trap_sig) {
|
|
|
d4bfbf |
+ wd->te = TE_SYSCALL_STOP;
|
|
|
d4bfbf |
+ } else {
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * True if tracee is stopped by signal
|
|
|
d4bfbf |
+ * (as opposed to "tracee received
|
|
|
d4bfbf |
+ * signal").
|
|
|
d4bfbf |
+ * TODO: shouldn't we check for
|
|
|
d4bfbf |
+ * errno == EINVAL too?
|
|
|
d4bfbf |
+ * We can get ESRCH instead, you know...
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ bool stopped = ptrace(PTRACE_GETSIGINFO,
|
|
|
d4bfbf |
+ pid, 0, &wd->si) < 0;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (WIFSIGNALED(status)) {
|
|
|
d4bfbf |
- wd->te = TE_SIGNALLED;
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
+ wd->te = stopped ? TE_GROUP_STOP
|
|
|
d4bfbf |
+ : TE_SIGNAL_DELIVERY_STOP;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ case PTRACE_EVENT_STOP:
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * PTRACE_INTERRUPT-stop or group-stop.
|
|
|
d4bfbf |
+ * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ switch (sig) {
|
|
|
d4bfbf |
+ case SIGSTOP:
|
|
|
d4bfbf |
+ case SIGTSTP:
|
|
|
d4bfbf |
+ case SIGTTIN:
|
|
|
d4bfbf |
+ case SIGTTOU:
|
|
|
d4bfbf |
+ wd->te = TE_GROUP_STOP;
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ default:
|
|
|
d4bfbf |
+ wd->te = TE_RESTART;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ case PTRACE_EVENT_EXEC:
|
|
|
d4bfbf |
+ /*
|
|
|
d4bfbf |
+ * TODO: shouldn't we check for
|
|
|
d4bfbf |
+ * errno == EINVAL here, too?
|
|
|
d4bfbf |
+ * We can get ESRCH instead, you know...
|
|
|
d4bfbf |
+ */
|
|
|
d4bfbf |
+ if (ptrace(PTRACE_GETEVENTMSG, pid, NULL,
|
|
|
d4bfbf |
+ &wd->msg) < 0)
|
|
|
d4bfbf |
+ wd->msg = 0;
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- if (WIFEXITED(status)) {
|
|
|
d4bfbf |
- wd->te = TE_EXITED;
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
+ wd->te = TE_STOP_BEFORE_EXECVE;
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ case PTRACE_EVENT_EXIT:
|
|
|
d4bfbf |
+ wd->te = TE_STOP_BEFORE_EXIT;
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+ default:
|
|
|
d4bfbf |
+ wd->te = TE_RESTART;
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (tcp->wait_list.next) {
|
|
|
d4bfbf |
+ wait_extra_data_idx = wait_tab_pos;
|
|
|
d4bfbf |
+ extra_tcp = tcp;
|
|
|
d4bfbf |
+ debug_func_msg("queued extra pid %d", tcp->pid);
|
|
|
d4bfbf |
+ } else {
|
|
|
d4bfbf |
+ tcp->wait_data_idx = wait_tab_pos;
|
|
|
d4bfbf |
+ list_append(&pending_tcps, &tcp->wait_list);
|
|
|
d4bfbf |
+ debug_func_msg("queued pid %d", tcp->pid);
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ wd->status = status;
|
|
|
d4bfbf |
+ wait_tab_pos++;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (extra_tcp)
|
|
|
d4bfbf |
+ break;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL));
|
|
|
d4bfbf |
+ wait_errno = errno;
|
|
|
d4bfbf |
+ wait_nohang = true;
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- /*
|
|
|
d4bfbf |
- * As WCONTINUED flag has not been specified to wait4,
|
|
|
d4bfbf |
- * it cannot be WIFCONTINUED(status), so the only case
|
|
|
d4bfbf |
- * that remains is WIFSTOPPED(status).
|
|
|
d4bfbf |
- */
|
|
|
d4bfbf |
+next_event_get_tcp:
|
|
|
d4bfbf |
+ elem = list_remove_head(&pending_tcps);
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ if (!elem) {
|
|
|
d4bfbf |
+ memset(tcb_wait_tab, 0, sizeof(*tcb_wait_tab));
|
|
|
d4bfbf |
+ tcb_wait_tab->te = TE_NEXT;
|
|
|
d4bfbf |
+
|
|
|
d4bfbf |
+ return tcb_wait_tab;
|
|
|
d4bfbf |
+ } else {
|
|
|
d4bfbf |
+ tcp = list_elem(elem, struct tcb, wait_list);
|
|
|
d4bfbf |
+ debug_func_msg("dequeued pid %d", tcp->pid);
|
|
|
d4bfbf |
+ }
|
|
|
d4bfbf |
|
|
|
d4bfbf |
+next_event_exit:
|
|
|
d4bfbf |
/* Is this the very first time we see this tracee stopped? */
|
|
|
d4bfbf |
if (tcp->flags & TCB_STARTUP)
|
|
|
d4bfbf |
startup_tcb(tcp);
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- const unsigned int sig = WSTOPSIG(status);
|
|
|
d4bfbf |
- const unsigned int event = (unsigned int) status >> 16;
|
|
|
d4bfbf |
+ clear_regs(tcp);
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- switch (event) {
|
|
|
d4bfbf |
- case 0:
|
|
|
d4bfbf |
- /*
|
|
|
d4bfbf |
- * Is this post-attach SIGSTOP?
|
|
|
d4bfbf |
- * Interestingly, the process may stop
|
|
|
d4bfbf |
- * with STOPSIG equal to some other signal
|
|
|
d4bfbf |
- * than SIGSTOP if we happened to attach
|
|
|
d4bfbf |
- * just before the process takes a signal.
|
|
|
d4bfbf |
- */
|
|
|
d4bfbf |
- if (sig == SIGSTOP && (tcp->flags & TCB_IGNORE_ONE_SIGSTOP)) {
|
|
|
d4bfbf |
- debug_func_msg("ignored SIGSTOP on pid %d", tcp->pid);
|
|
|
d4bfbf |
- tcp->flags &= ~TCB_IGNORE_ONE_SIGSTOP;
|
|
|
d4bfbf |
- wd->te = TE_RESTART;
|
|
|
d4bfbf |
- } else if (sig == syscall_trap_sig) {
|
|
|
d4bfbf |
- wd->te = TE_SYSCALL_STOP;
|
|
|
d4bfbf |
- } else {
|
|
|
d4bfbf |
- memset(&wd->si, 0, sizeof(wd->si));
|
|
|
d4bfbf |
- /*
|
|
|
d4bfbf |
- * True if tracee is stopped by signal
|
|
|
d4bfbf |
- * (as opposed to "tracee received signal").
|
|
|
d4bfbf |
- * TODO: shouldn't we check for errno == EINVAL too?
|
|
|
d4bfbf |
- * We can get ESRCH instead, you know...
|
|
|
d4bfbf |
- */
|
|
|
d4bfbf |
- bool stopped = ptrace(PTRACE_GETSIGINFO, pid, 0, &wd->si) < 0;
|
|
|
d4bfbf |
- wd->te = stopped ? TE_GROUP_STOP : TE_SIGNAL_DELIVERY_STOP;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
- break;
|
|
|
d4bfbf |
- case PTRACE_EVENT_STOP:
|
|
|
d4bfbf |
- /*
|
|
|
d4bfbf |
- * PTRACE_INTERRUPT-stop or group-stop.
|
|
|
d4bfbf |
- * PTRACE_INTERRUPT-stop has sig == SIGTRAP here.
|
|
|
d4bfbf |
- */
|
|
|
d4bfbf |
- switch (sig) {
|
|
|
d4bfbf |
- case SIGSTOP:
|
|
|
d4bfbf |
- case SIGTSTP:
|
|
|
d4bfbf |
- case SIGTTIN:
|
|
|
d4bfbf |
- case SIGTTOU:
|
|
|
d4bfbf |
- wd->te = TE_GROUP_STOP;
|
|
|
d4bfbf |
- break;
|
|
|
d4bfbf |
- default:
|
|
|
d4bfbf |
- wd->te = TE_RESTART;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
- break;
|
|
|
d4bfbf |
- case PTRACE_EVENT_EXEC:
|
|
|
d4bfbf |
- wd->te = TE_STOP_BEFORE_EXECVE;
|
|
|
d4bfbf |
- break;
|
|
|
d4bfbf |
- case PTRACE_EVENT_EXIT:
|
|
|
d4bfbf |
- wd->te = TE_STOP_BEFORE_EXIT;
|
|
|
d4bfbf |
- break;
|
|
|
d4bfbf |
- default:
|
|
|
d4bfbf |
- wd->te = TE_RESTART;
|
|
|
d4bfbf |
- }
|
|
|
d4bfbf |
+ /* Set current output file */
|
|
|
d4bfbf |
+ set_current_tcp(tcp);
|
|
|
d4bfbf |
|
|
|
d4bfbf |
- return wd;
|
|
|
d4bfbf |
+ return tcb_wait_tab + tcp->wait_data_idx;
|
|
|
d4bfbf |
}
|
|
|
d4bfbf |
|
|
|
d4bfbf |
static int
|
|
|
d4bfbf |
Index: strace-4.24/tests/Makefile.am
|
|
|
d4bfbf |
===================================================================
|
|
|
d4bfbf |
--- strace-4.24.orig/tests/Makefile.am 2018-09-12 23:53:31.739527473 +0200
|
|
|
d4bfbf |
+++ strace-4.24/tests/Makefile.am 2018-09-12 23:53:35.765480919 +0200
|
|
|
d4bfbf |
@@ -367,8 +367,7 @@
|
|
|
d4bfbf |
XFAIL_TESTS_mx32 = $(STACKTRACE_TESTS)
|
|
|
d4bfbf |
XFAIL_TESTS_x86_64 = int_0x80.gen.test
|
|
|
d4bfbf |
XFAIL_TESTS_x32 = int_0x80.gen.test
|
|
|
d4bfbf |
-XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) $(XFAIL_TESTS_$(ARCH)) \
|
|
|
d4bfbf |
- looping_threads.test
|
|
|
d4bfbf |
+XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) $(XFAIL_TESTS_$(ARCH))
|
|
|
d4bfbf |
|
|
|
d4bfbf |
TEST_LOG_COMPILER = env
|
|
|
d4bfbf |
AM_TEST_LOG_FLAGS = STRACE_ARCH=$(ARCH) STRACE_NATIVE_ARCH=$(NATIVE_ARCH) \
|