diff -ur strace-5.5/delay.h strace-5.5.y/delay.h --- strace-5.5/delay.h 2019-08-06 15:38:20.000000000 +0200 +++ strace-5.5.y/delay.h 2020-02-29 12:39:51.563110827 +0100 @@ -14,5 +14,6 @@ void delay_timer_expired(void); void arm_delay_timer(const struct tcb *); void delay_tcb(struct tcb *, uint16_t delay_idx, bool isenter); +int my_waitpid(int, int*, int); #endif /* !STRACE_DELAY_H */ diff -ur strace-5.5/filter_seccomp.c strace-5.5.y/filter_seccomp.c --- strace-5.5/filter_seccomp.c 2020-02-06 16:16:17.000000000 +0100 +++ strace-5.5.y/filter_seccomp.c 2020-02-29 12:42:43.184120263 +0100 @@ -19,6 +19,7 @@ #include "number_set.h" #include "syscall.h" #include "scno.h" +#include "delay.h" bool seccomp_filtering; bool seccomp_before_sysentry; @@ -136,7 +137,7 @@ int status; for (;;) { - long rc = waitpid(pid, &status, 0); + long rc = my_waitpid(pid, &status, 0); if (rc < 0 && errno == EINTR) continue; if (rc == pid) @@ -272,7 +273,7 @@ if (pid) { kill(pid, SIGKILL); for (;;) { - long rc = waitpid(pid, NULL, 0); + long rc = my_waitpid(pid, NULL, 0); if (rc < 0 && errno == EINTR) continue; break; diff -ur strace-5.5/Makefile.am strace-5.5.y/Makefile.am --- strace-5.5/Makefile.am 2020-02-06 16:16:17.000000000 +0100 +++ strace-5.5.y/Makefile.am 2020-02-29 10:28:04.515676065 +0100 @@ -45,7 +45,7 @@ strace_CPPFLAGS = $(AM_CPPFLAGS) strace_CFLAGS = $(AM_CFLAGS) strace_LDFLAGS = -strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS) +strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS) noinst_LIBRARIES = libstrace.a libstrace_a_CPPFLAGS = $(strace_CPPFLAGS) diff -ur strace-5.5/Makefile.in strace-5.5.y/Makefile.in --- strace-5.5/Makefile.in 2020-02-06 17:23:35.000000000 +0100 +++ strace-5.5.y/Makefile.in 2020-02-29 10:28:28.833677402 +0100 @@ -1631,7 +1631,7 @@ $(am__append_11) $(CODE_COVERAGE_CPPFLAGS) strace_CFLAGS = $(AM_CFLAGS) $(am__append_4) $(CODE_COVERAGE_CFLAGS) strace_LDFLAGS = $(am__append_5) $(am__append_9) $(am__append_12) -strace_LDADD = libstrace.a $(clock_LIBS) $(timer_LIBS) $(am__append_6) \ +strace_LDADD = libstrace.a -lpthread $(clock_LIBS) $(timer_LIBS) $(am__append_6) \ $(am__append_10) $(am__append_13) $(CODE_COVERAGE_LIBS) \ $(am__append_14) $(am__append_18) noinst_LIBRARIES = libstrace.a $(am__append_15) $(am__append_19) diff -ur strace-5.5/strace.c strace-5.5.y/strace.c --- strace-5.5/strace.c 2020-02-06 16:16:17.000000000 +0100 +++ strace-5.5.y/strace.c 2020-03-01 07:59:55.586429063 +0100 @@ -15,6 +15,8 @@ #include #include "ptrace.h" #include +#include +#include #include #include #ifdef HAVE_PATHS_H @@ -69,7 +71,7 @@ cflag_t cflag = CFLAG_NONE; unsigned int followfork; unsigned int ptrace_setoptions = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC - | PTRACE_O_TRACEEXIT; + ;//| PTRACE_O_TRACEEXIT; unsigned int xflag; bool debug_flag; bool Tflag; @@ -1002,7 +1004,7 @@ */ for (;;) { unsigned int sig; - if (waitpid(tcp->pid, &status, __WALL) < 0) { + if (my_waitpid(tcp->pid, &status, __WALL) < 0) { if (errno == EINTR) continue; /* @@ -1663,6 +1665,83 @@ sigaction(signo, &sa, oldact); } +#define MAX_WAITIDX 65536 +static unsigned short in_idx = 0, out_idx = 0; +static sem_t wait_sem; +static pthread_t wait_thread; +static int wait_pid[MAX_WAITIDX]; +static int wait_status[MAX_WAITIDX]; +static struct rusage wait_rusage[MAX_WAITIDX]; + +static void* +child_sighandler(void *arg) +{ + int status; + struct rusage ru; + int pid; + for (;;) { + pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL)); + if (pid < 0 && errno == EINTR) + continue; + + if (pid < 0) + pid = -errno; + + if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) { + int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L); + fprintf(stderr, "in thread: ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno); + } + wait_pid[in_idx] = pid; + wait_status[in_idx] = status; + if (cflag) + wait_rusage[in_idx] = ru; + in_idx++; + if (in_idx == out_idx || sem_post(&wait_sem) == -1) + error_msg_and_die("fatal error in child_sighandler"); + if (pid < 0) + break; + } + + return NULL; +} + +int my_waitpid(int pid, int *status, int options) +{ + int skip = 0; + unsigned short idx = out_idx; + for (;;) { + while (sem_wait(&wait_sem) == -1 && errno == EINTR) + ; + if (wait_pid[idx] < 0) { + while (skip-- >= 0) + sem_post(&wait_sem); + errno = -wait_pid[idx]; + return -1; + } + if (wait_pid[idx] == pid) + break; + idx++; + skip++; + } + *status = wait_status[idx]; + while (skip > 0) { + unsigned short idx1 = idx; + idx1--; + wait_status[idx] = wait_status[idx1]; + wait_pid[idx] = wait_pid[idx1]; + if (cflag) + wait_rusage[idx] = wait_rusage[idx1]; + if (sem_post(&wait_sem) == -1) + error_msg_and_die("fatal error in my_waitpid"); + skip--; + idx--; + } + out_idx++; + if (pid < 0) + errno = -pid; + return pid < 0 ? -1 : pid; +} + /* * Initialization part of main() was eating much stack (~0.5k), * which was unused after init. @@ -2124,6 +2203,9 @@ startup_child(argv); } + if (sem_init(&wait_sem, 0, 0) == -1) + perror_msg_and_die("Unable to initialize signal wait sema"); + set_sighandler(SIGTTOU, SIG_IGN, NULL); set_sighandler(SIGTTIN, SIG_IGN, NULL); if (opt_intr != INTR_ANYWHERE) { @@ -2150,6 +2232,7 @@ if (nprocs != 0 || daemonized_tracer) startup_attach(); + pthread_create(&wait_thread, NULL, child_sighandler, NULL); /* Do we want pids printed in our -o OUTFILE? * -ff: no (every pid has its own file); or * -f: yes (there can be more pids in the future); or @@ -2607,10 +2690,28 @@ * then the system call will be interrupted and * the expiration will be handled by the signal handler. */ - int status; + int status = 0; struct rusage ru; - int pid = wait4(-1, &status, __WALL, (cflag ? &ru : NULL)); - int wait_errno = errno; + int pid = 0; + int wait_errno = 0; + while (sem_wait(&wait_sem) == -1 && errno == EINTR) + ; + + if (in_idx == out_idx) + error_msg_and_die("wait queue error"); + pid = wait_pid[out_idx]; + status = wait_status[out_idx]; + ru = wait_rusage[out_idx]; + if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) { + int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L); + fprintf(stderr, "ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno); + } + out_idx++; + if (pid < 0) { + wait_errno = -pid; + out_idx--; + sem_post(&wait_sem); + } /* * The window of opportunity to handle expirations @@ -2791,8 +2892,25 @@ break; next_event_wait_next: - pid = wait4(-1, &status, __WALL | WNOHANG, (cflag ? &ru : NULL)); - wait_errno = errno; + pid = 0; + if (in_idx != out_idx) { + while (sem_wait(&wait_sem) == -1 && errno == EINTR) + ; + + pid = wait_pid[out_idx]; + status = wait_status[out_idx]; + ru = wait_rusage[out_idx]; + if (pid > 0 && WIFSTOPPED(status) && (status >> 16) == PTRACE_EVENT_EXIT) { + int i = ptrace(PTRACE_SYSCALL, pid, 0L, 0L); + fprintf(stderr, "ptrace(PTRACE_SYSCALL, %d, 0L, 0L)=%d errno=%d\n", pid, i, errno); + } + out_idx++; + if (pid < 0) { + wait_errno = -pid; + out_idx--; + sem_post(&wait_sem); + } + } wait_nohang = true; } @@ -3019,7 +3137,8 @@ case TE_STOP_BEFORE_EXIT: print_event_exit(current_tcp); - break; + //droptcb(current_tcp); + return true; } /* We handled quick cases, we are permitted to interrupt now. */ @@ -3138,9 +3257,10 @@ if (shared_log != stderr) fclose(shared_log); if (popen_pid) { - while (waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR) + while (my_waitpid(popen_pid, NULL, 0) < 0 && errno == EINTR) ; } + pthread_join(wait_thread, NULL); if (sig) { exit_code = 0x100 | sig; }