Index: usr.bin/truss/extern.h =================================================================== --- usr.bin/truss/extern.h +++ usr.bin/truss/extern.h @@ -34,6 +34,5 @@ extern int print_line_prefix(struct trussinfo *); extern void setup_and_wait(struct trussinfo *, char **); extern void start_tracing(struct trussinfo *, pid_t); -extern void restore_proc(int); extern void eventloop(struct trussinfo *); extern const char *ioctlname(unsigned long val); Index: usr.bin/truss/main.c =================================================================== --- usr.bin/truss/main.c +++ usr.bin/truss/main.c @@ -65,7 +65,6 @@ int main(int ac, char **av) { - struct sigaction sa; struct trussinfo *trussinfo; char *fname; char **command; @@ -143,26 +142,11 @@ err(1, "cannot open %s", fname); } - /* - * If truss starts the process itself, it will ignore some signals -- - * they should be passed off to the process, which may or may not - * exit. If, however, we are examining an already-running process, - * then we restore the event mask on these same signals. - */ if (pid == 0) { /* Start a command ourselves */ command = av; setup_and_wait(trussinfo, command); - signal(SIGINT, SIG_IGN); - signal(SIGTERM, SIG_IGN); - signal(SIGQUIT, SIG_IGN); } else { - sa.sa_handler = restore_proc; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGQUIT, &sa, NULL); - sigaction(SIGTERM, &sa, NULL); start_tracing(trussinfo, pid); } Index: usr.bin/truss/setup.c =================================================================== --- usr.bin/truss/setup.c +++ usr.bin/truss/setup.c @@ -61,16 +61,29 @@ SET_DECLARE(procabi, struct procabi); static sig_atomic_t detaching; +static pid_t new_child; static void enter_syscall(struct trussinfo *, struct threadinfo *, struct ptrace_lwpinfo *); static void new_proc(struct trussinfo *, pid_t, lwpid_t); +static void restore_proc(int); +static void +forward_signal(int signo) +{ + + kill(new_child, signo); +} + /* - * setup_and_wait() is called to start a process. All it really does - * is fork(), enable tracing in the child, and then exec the given + * setup_and_wait() is called to start a process. First, it fork()s a new + * child, enables tracing in the child, and then execs the given * command. At that point, the child process stops, and the parent * can wake up and deal with it. + * + * A signal handler is installed for SIGINT, SIGTERM, and SIGQUIT + * which forwards signals received by truss to the new child process + * so that truss is transparent from the shell's perspective. */ void setup_and_wait(struct trussinfo *info, char *command[]) @@ -81,6 +94,7 @@ if (pid == -1) err(1, "fork failed"); if (pid == 0) { /* Child */ + setpgid(0, 0); ptrace(PT_TRACE_ME, 0, 0, 0); execvp(command[0], command); err(1, "execvp %s", command[0]); @@ -90,6 +104,10 @@ if (waitpid(pid, NULL, 0) < 0) err(1, "unexpect stop in waitpid"); + new_child = pid; + signal(SIGINT, forward_signal); + signal(SIGTERM, forward_signal); + signal(SIGQUIT, forward_signal); new_proc(info, pid, 0); } @@ -99,8 +117,15 @@ void start_tracing(struct trussinfo *info, pid_t pid) { + struct sigaction sa; int ret, retry; + sa.sa_handler = restore_proc; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGQUIT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); retry = 10; do { ret = ptrace(PT_ATTACH, pid, NULL, 0); @@ -121,7 +146,7 @@ * applies if truss was told to monitor an already-existing * process. */ -void +static void restore_proc(int signo __unused) {