Implement simultaneous use of -p option and tracing of a command
* strace.c (init): Allow -p option along with a command.
(startup_child): In -D mode, record the parent of the tracer process
as strace_child.
(startup_attach): Save trace_tracer_pid before -D mode fork.
When tracing a command in -f mode, do not check for the command's
threads as it has no threads at this moment.
Never attach to the tracer process.
In -D mode, never attach to the parent of the tracer process,
terminate that process only once at the end of startup_attach,
and reset strace_child.
* strace.1: Document that -p option can be used along with tracing
of a command.
* NEWS: Mention it.
* tests/attach-p-cmd-cmd.c: New file.
* tests/attach-p-cmd-p.c: Likewise.
* tests/attach-p-cmd.test: New test.
* tests/.gitignore: Add attach-p-cmd-cmd and attach-p-cmd-p.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(TESTS): Add attach-p-cmd.test.
This fixes Debian bug #549942.
diff --git a/strace.c b/strace.c
index 7792a5c..614b85f 100644
--- a/strace.c
+++ b/strace.c
@@ -973,6 +973,7 @@
static void
startup_attach(void)
{
+ pid_t parent_pid = strace_tracer_pid;
unsigned int tcbi;
struct tcb *tcp;
@@ -1015,7 +1016,13 @@
if (tcp->flags & TCB_ATTACHED)
continue; /* no, we already attached it */
- if (followfork && !daemonized_tracer) {
+ if (tcp->pid == parent_pid || tcp->pid == strace_tracer_pid) {
+ errno = EPERM;
+ perror_msg("attach: %d", tcp->pid);
+ droptcb(tcp);
+ continue;
+ }
+ if (followfork && tcp->pid != strace_child) {
char procdir[sizeof("/proc/%d/task") + sizeof(int) * 3];
DIR *dir;
@@ -1092,18 +1099,19 @@
if (debug_flag)
error_msg("attach to pid %d (main) succeeded", tcp->pid);
- if (daemonized_tracer) {
- /*
- * Make parent go away.
- * Also makes grandparent's wait() unblock.
- */
- kill(getppid(), SIGKILL);
- }
-
if (!qflag)
error_msg("Process %u attached", tcp->pid);
} /* for each tcbtab[] */
+ if (daemonized_tracer) {
+ /*
+ * Make parent go away.
+ * Also makes grandparent's wait() unblock.
+ */
+ kill(parent_pid, SIGKILL);
+ strace_child = 0;
+ }
+
ret:
if (interactive)
sigprocmask(SIG_SETMASK, &empty_set, NULL);
@@ -1317,11 +1325,10 @@
newoutf(tcp);
}
else {
- /* With -D, we are *child* here, IOW: different pid. Fetch it: */
+ /* With -D, we are *child* here, the tracee is our parent. */
+ strace_child = strace_tracer_pid;
strace_tracer_pid = getpid();
- /* The tracee is our parent: */
- pid = getppid();
- alloctcb(pid);
+ alloctcb(strace_child);
/* attaching will be done later, by startup_attach */
/* note: we don't do newoutf(tcp) here either! */
@@ -1619,13 +1626,12 @@
memset(acolumn_spaces, ' ', acolumn);
acolumn_spaces[acolumn] = '\0';
- /* Must have PROG [ARGS], or -p PID. Not both. */
- if (!argv[0] == !nprocs) {
+ if (!argv[0] && !nprocs) {
error_msg_and_help("must have PROG [ARGS] or -p PID");
}
- if (nprocs != 0 && daemonized_tracer) {
- error_msg_and_help("-D and -p are mutually exclusive");
+ if (!argv[0] && daemonized_tracer) {
+ error_msg_and_help("PROG [ARGS] must be specified with -D");
}
if (!followfork)
@@ -1722,9 +1728,9 @@
opt_intr = INTR_WHILE_WAIT;
/* argv[0] -pPID -oFILE Default interactive setting
- * yes 0 0 INTR_WHILE_WAIT
+ * yes * 0 INTR_WHILE_WAIT
* no 1 0 INTR_WHILE_WAIT
- * yes 0 1 INTR_NEVER
+ * yes * 1 INTR_NEVER
* no 1 1 INTR_WHILE_WAIT
*/