Index: usr.bin/truss/setup.c =================================================================== --- usr.bin/truss/setup.c (revision 240005) +++ usr.bin/truss/setup.c (working copy) @@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$"); #include "truss.h" #include "extern.h" -static pid_t child_pid; +static sig_atomic_t detaching; /* * setup_and_wait() is called to start a process. All it really does @@ -70,7 +70,6 @@ int setup_and_wait(char *command[]) { pid_t pid; - int waitval; pid = vfork(); if (pid == -1) @@ -82,13 +81,11 @@ setup_and_wait(char *command[]) } /* Only in the parent here */ - if (waitpid(pid, &waitval, 0) < 0) { + if (waitpid(pid, NULL, 0) < 0) { err(1, "unexpect stop in waitpid"); return 0; } - child_pid = pid; - return (pid); } @@ -101,7 +98,7 @@ setup_and_wait(char *command[]) int start_tracing(pid_t pid) { - int ret, retry, waitval; + int ret, retry; retry = 10; do { @@ -111,8 +108,7 @@ start_tracing(pid_t pid) if (ret) err(1, "can not attach to target process"); - child_pid = pid; - if (waitpid(pid, &waitval, 0) < 0) + if (waitpid(pid, NULL, 0) < 0) err(1, "Unexpect stop in waitpid"); return (0); @@ -124,21 +120,30 @@ start_tracing(pid_t pid) * applies if truss was told to monitor an already-existing * process. */ + void restore_proc(int signo __unused) { + + detaching = 1; +} + +static int +detach_proc(struct trussinfo *info) +{ int waitval; /* stop the child so that we can detach */ - kill(child_pid, SIGSTOP); - if (waitpid(child_pid, &waitval, 0) < 0) + kill(info->pid, SIGSTOP); + if (waitpid(info->pid, &waitval, 0) < 0) err(1, "Unexpected stop in waitpid"); - if (ptrace(PT_DETACH, child_pid, (caddr_t)1, 0) < 0) + if (ptrace(PT_DETACH, info->pid, (caddr_t)1, 0) < 0) err(1, "Can not detach the process"); - kill(child_pid, SIGCONT); - exit(0); + kill(info->pid, SIGCONT); + + return (waitval); } /* @@ -183,8 +188,19 @@ waitevent(struct trussinfo *info) ptrace(PT_SYSCALL, info->pid, (caddr_t)1, pending_signal); pending_signal = 0; - if (waitpid(info->pid, &waitval, 0) < 0) +detach: + if (detaching) { + waitval = detach_proc(info); + info->pr_why = S_DETACHED; + info->pr_data = WEXITSTATUS(waitval); + return; + } + + if (waitpid(info->pid, &waitval, 0) == -1) { + if (errno == EINTR) + goto detach; err(1, "Unexpected stop in waitpid"); + } if (WIFCONTINUED(waitval)) { info->pr_why = S_NONE; Index: usr.bin/truss/main.c =================================================================== --- usr.bin/truss/main.c (revision 240005) +++ usr.bin/truss/main.c (working copy) @@ -163,6 +163,7 @@ strsig(int sig) int main(int ac, char **av) { + struct sigaction sa; struct ex_types *funcs; struct trussinfo *trussinfo; char *fname; @@ -257,10 +258,13 @@ main(int ac, char **av) 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); - signal(SIGINT, restore_proc); - signal(SIGTERM, restore_proc); - signal(SIGQUIT, restore_proc); } @@ -366,7 +370,8 @@ START_TRACE: default: break; } - } while (trussinfo->pr_why != S_EXIT); + } while (trussinfo->pr_why != S_EXIT && + trussinfo->pr_why != S_DETACHED); if (trussinfo->flags & FOLLOWFORKS) { do { Index: usr.bin/truss/truss.h =================================================================== --- usr.bin/truss/truss.h (revision 240005) +++ usr.bin/truss/truss.h (working copy) @@ -87,3 +87,4 @@ struct trussinfo #define S_EXIT 3 #define S_SIG 4 #define S_EXEC 5 +#define S_DETACHED 6