svn commit: r240393 - head/usr.bin/truss
Andrey Zonov
zont at FreeBSD.org
Wed Sep 12 13:06:58 UTC 2012
Author: zont
Date: Wed Sep 12 13:06:57 2012
New Revision: 240393
URL: http://svn.freebsd.org/changeset/base/240393
Log:
- 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
Modified:
head/usr.bin/truss/main.c
head/usr.bin/truss/setup.c
head/usr.bin/truss/truss.h
Modified: head/usr.bin/truss/main.c
==============================================================================
--- head/usr.bin/truss/main.c Wed Sep 12 12:14:50 2012 (r240392)
+++ head/usr.bin/truss/main.c Wed Sep 12 13:06:57 2012 (r240393)
@@ -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 {
Modified: head/usr.bin/truss/setup.c
==============================================================================
--- head/usr.bin/truss/setup.c Wed Sep 12 12:14:50 2012 (r240392)
+++ head/usr.bin/truss/setup.c Wed Sep 12 13:06:57 2012 (r240393)
@@ -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;
Modified: head/usr.bin/truss/truss.h
==============================================================================
--- head/usr.bin/truss/truss.h Wed Sep 12 12:14:50 2012 (r240392)
+++ head/usr.bin/truss/truss.h Wed Sep 12 13:06:57 2012 (r240393)
@@ -87,3 +87,4 @@ struct trussinfo
#define S_EXIT 3
#define S_SIG 4
#define S_EXEC 5
+#define S_DETACHED 6
More information about the svn-src-head
mailing list