Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Sep 2012 13:06:57 +0000 (UTC)
From:      Andrey Zonov <zont@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r240393 - head/usr.bin/truss
Message-ID:  <201209121306.q8CD6v67072686@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201209121306.q8CD6v67072686>