.BR "" {
.OR \-p pid
.BR "" |
-.OP \-D
+.OP \-DDD
.OM \-E var\fR[=\fIval\fR]
.OP \-u username
.IR command " [" args ]
.BR "" {
.OR \-p pid
.BR "" |
-.OP \-D
+.OP \-DDD
.OM \-E var\fR[=\fIval\fR]
.OP -u username
.IR command " [" args ]
but don't want to trace its (potentially very complex) children.
.TP
.B \-D
-Run tracer process as a detached grandchild, not as parent of the
+Run tracer process as a grandchild, not as the parent of the
tracee. This reduces the visible effect of
.B strace
by keeping the tracee a direct child of the calling process.
.TP
+.B \-DD
+Run tracer process as tracee's grandchild in a separate process group.
+In addition to reduction of the visible effect of
+.BR strace ,
+it also avoids killing of
+.B strace
+with
+.BR kill (2)
+issued to the whole process group.
+.TP
+.B \-DDD
+Run tracer process as tracee's grandchild in a separate session
+("true daemonisation").
+In addition to reduction of the visible effect of
+.BR strace ,
+it also avoids killing of
+.B strace
+upon session termination.
+.TP
.B \-f
Trace child processes as they are created by currently traced
processes as a result of the
/* We play with signal mask only if this mode is active: */
#define interactive (opt_intr == INTR_WHILE_WAIT)
+enum {
+ DAEMONIZE_NONE = 0,
+ DAEMONIZE_GRANDCHILD = 1,
+ DAEMONIZE_NEW_PGROUP = 2,
+ DAEMONIZE_NEW_SESSION = 3,
+
+ DAEMONIZE_OPTS_GUARD__,
+ MAX_DAEMONIZE_OPTS = DAEMONIZE_OPTS_GUARD__ - 1
+};
/*
* daemonized_tracer supports -D option.
* With this option, strace forks twice.
* wait() etc. Without -D, strace process gets lodged in between,
* disrupting parent<->child link.
*/
-static bool daemonized_tracer;
+static unsigned int daemonized_tracer;
static int post_attach_sigstop = TCB_IGNORE_ONE_SIGSTOP;
#define use_seize (post_attach_sigstop == 0)
usage: strace [-ACdffhi" K_OPT "qqrtttTvVwxxyyzZ] [-I n] [-b execve] [-e expr]...\n\
[-a column] [-o file] [-s strsize] [-X format] [-P path]...\n\
[-p pid]... [--seccomp-bpf]\n\
- { -p pid | [-D] [-E var=val]... [-u username] PROG [ARGS] }\n\
+ { -p pid | [-DDD] [-E var=val]... [-u username] PROG [ARGS] }\n\
or: strace -c[dfwzZ] [-I n] [-b execve] [-e expr]... [-O overhead]\n\
[-S sortby] [-P path]... [-p pid]... [--seccomp-bpf]\n\
- { -p pid | [-D] [-E var=val]... [-u username] PROG [ARGS] }\n\
+ { -p pid | [-DDD] [-E var=val]... [-u username] PROG [ARGS] }\n\
\n\
Output format:\n\
-A open the file provided in the -o option in append mode\n\
\n\
Tracing:\n\
-b execve detach on execve syscall\n\
- -D run tracer process as a detached grandchild, not as parent\n\
+ -D run tracer process as a grandchild, not as a parent\n\
+ -DD run tracer process in a separate process group\n\
+ -DDD run tracer process in a separate session\n\
-f follow forks\n\
-ff follow forks with output into separate files\n\
-I interruptible\n\
/* grandchild */
/* We will be the tracer process. Remember our new pid: */
strace_tracer_pid = getpid();
+
+ switch (daemonized_tracer) {
+ case DAEMONIZE_NEW_PGROUP:
+ /*
+ * If -D is passed twice, create a new process group,
+ * so we won't be killed by kill(0, ...).
+ */
+ if (setpgid(0, 0) < 0)
+ perror_msg_and_die("Cannot create a new"
+ " process group");
+ break;
+ case DAEMONIZE_NEW_SESSION:
+ /*
+ * If -D is passed thrice, create a new session,
+ * so we won't be killed upon session termination.
+ */
+ if (setsid() < 0)
+ perror_msg_and_die("Cannot create a new"
+ " session");
+ break;
+ }
}
for (tcbi = 0; tcbi < tcbtabsize; tcbi++) {
debug_flag = 1;
break;
case 'D':
- daemonized_tracer = 1;
+ daemonized_tracer++;
break;
case 'e':
qualify(optarg);
error_msg_and_help("PROG [ARGS] must be specified with -D");
}
+ if (daemonized_tracer > (unsigned int) MAX_DAEMONIZE_OPTS)
+ error_msg_and_help("Too many -D's (%u), maximum supported -D "
+ "count is %d",
+ daemonized_tracer, MAX_DAEMONIZE_OPTS);
+
if (seccomp_filtering && detach_on_execve) {
error_msg("--seccomp-bpf is not enabled because"
" it is not compatible with -b");