- Fix detaching under some circumstances.
When truss is detaching from very active process it is possible to hang on waitpid(2) in restore_proc() forever, because ptrace(PT_SYSCALL) must be called before detaching, to allow the debugging process to continue execution. Also when truss called with '-c' argument, it does not print anything after detach, because it immediately exits from restore_proc(). To fix these two problems make detaching deferred, but then it is impossible to detach from a process which does not do any system call. To fix this issue use sigaction(2) instead of signal(3) to disable SA_RESTART flag for waitpid(2) that makes it non-restartable. Remove global variable child_pid, because now detaching is handled in context where child's pid is known. Reported by: mjg Tested by: mjg, swills Approved by: kib (mentor) MFC after: 2 weeks
This commit is contained in:
parent
d1b835208a
commit
896fc4638a
@ -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 @@ main(int ac, char **av)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while (trussinfo->pr_why != S_EXIT);
|
||||
} while (trussinfo->pr_why != S_EXIT &&
|
||||
trussinfo->pr_why != S_DETACHED);
|
||||
|
||||
if (trussinfo->flags & FOLLOWFORKS) {
|
||||
do {
|
||||
|
@ -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;
|
||||
|
@ -87,3 +87,4 @@ struct trussinfo
|
||||
#define S_EXIT 3
|
||||
#define S_SIG 4
|
||||
#define S_EXEC 5
|
||||
#define S_DETACHED 6
|
||||
|
Loading…
Reference in New Issue
Block a user