diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c index d6a1edc08a43..cb97293d381f 100644 --- a/usr.bin/truss/main.c +++ b/usr.bin/truss/main.c @@ -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 { diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c index 1ae300a8669a..c855c330008c 100644 --- a/usr.bin/truss/setup.c +++ b/usr.bin/truss/setup.c @@ -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 @@ -84,8 +84,6 @@ setup_and_wait(char *command[]) if (waitpid(pid, NULL, 0) < 0) err(1, "unexpect stop in waitpid"); - child_pid = pid; - return (pid); } @@ -108,7 +106,6 @@ start_tracing(pid_t pid) if (ret) err(1, "can not attach to target process"); - child_pid = pid; if (waitpid(pid, NULL, 0) < 0) err(1, "Unexpect stop in waitpid"); @@ -121,21 +118,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(pid_t pid) { int waitval; /* stop the child so that we can detach */ - kill(child_pid, SIGSTOP); - if (waitpid(child_pid, &waitval, 0) < 0) + kill(pid, SIGSTOP); + if (waitpid(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, pid, (caddr_t)1, 0) < 0) err(1, "Can not detach the process"); - kill(child_pid, SIGCONT); - exit(0); + kill(pid, SIGCONT); + + return (waitval); } /* @@ -180,8 +186,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->pid); + 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; diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h index d09886e8ef69..7dd87f54276a 100644 --- a/usr.bin/truss/truss.h +++ b/usr.bin/truss/truss.h @@ -87,3 +87,4 @@ struct trussinfo #define S_EXIT 3 #define S_SIG 4 #define S_EXEC 5 +#define S_DETACHED 6