Date: Wed, 15 Sep 2004 11:46:25 +1000 (EST) From: Sam Lawrance <boris@brooknet.com.au> To: FreeBSD-gnats-submit@FreeBSD.org Subject: bin/71749: [PATCH] truss -f causes circular wait when traced process vforks Message-ID: <20040915014625.2D021AAF@localhost> Resent-Message-ID: <200409150150.i8F1oKdZ035961@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 71749 >Category: bin >Synopsis: [PATCH] truss -f causes circular wait when traced process vforks >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Sep 15 01:50:20 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Sam Lawrance >Release: FreeBSD 5.3-BETA4 i386 >Organization: >Environment: System: FreeBSD dirk.no.domain 5.3-BETA4 FreeBSD 5.3-BETA4 #1: Wed Sep 15 01:21:24 EST 2004 root@dirk.no.domain:/usr/src/sys/i386/compile/GENERIC i386 >Description: Truss can't follow processes that vfork() because of a circular wait condition. Truss assumes calls to fork in the traced process return immediately with the child PID. On return, truss forks a child truss to trace the child process. Unfortunately, vfork() doesn't return the PID until the child has exited or exec'd. The circular wait is as follows: 1. Truss waits for vfork to return, so it can examine the PID and start a child truss to trace the child process. 2. The child process meanwhile has been started with the same pfsflags as the parent, so it will have stopped at the first syscall waiting for the child truss to PIOCCONT it. 3. But the child truss hasn't been started yet... back to (1). Apparently devel/strace had similar problems under linux. The strace fix is to actually poke user data and change vforks into forks. >How-To-Repeat: In any port directory, truss -f make clean always does the trick for me. >Fix: --- truss-patch begins here --- This patch adds and uses S_FWAIT, stop on fork/wait. This allows tracing processes to be informed of the child PID before the syscall returns, allowing them to take action where previously they would be stuck waiting. Index: sys/sys/pioctl.h =================================================================== RCS file: /home/ncvs/FreeBSD/src/sys/sys/pioctl.h,v retrieving revision 1.12 diff -u -u -r1.12 pioctl.h --- sys/sys/pioctl.h 4 Aug 2002 01:06:58 -0000 1.12 +++ sys/sys/pioctl.h 15 Sep 2004 00:59:55 -0000 @@ -65,7 +65,8 @@ # define S_SCX 0x00000008 /* stop on syscall exit */ # define S_CORE 0x00000010 /* stop on coredump */ # define S_EXIT 0x00000020 /* stop on exit */ -# define S_ALLSTOPS 0x003f /* stop on all events */ +# define S_FWAIT 0x00000040 /* stop on fork/wait (vfork) */ +# define S_ALLSTOPS 0x007f /* stop on all events */ /* * If PF_LINGER is set in procp->p_pfsflags, then the last close Index: sys/kern/kern_fork.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/sys/kern/kern_fork.c,v retrieving revision 1.234.2.3 diff -u -u -r1.234.2.3 kern_fork.c --- sys/kern/kern_fork.c 9 Sep 2004 10:03:19 -0000 1.234.2.3 +++ sys/kern/kern_fork.c 15 Sep 2004 00:57:31 -0000 @@ -716,6 +716,13 @@ */ KNOTE_LOCKED(&p1->p_klist, NOTE_FORK | p2->p_pid); + /* + * If fork in parent won't return before child exits, + * inform tracing processes so they may act. + */ + if (flags & RFPPWAIT) + _STOPEVENT(p1, S_FWAIT, p2->p_pid); + PROC_UNLOCK(p1); /* Index: usr.bin/truss/alpha-fbsd.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/alpha-fbsd.c,v retrieving revision 1.18 diff -u -u -r1.18 alpha-fbsd.c --- usr.bin/truss/alpha-fbsd.c 17 Jul 2004 19:48:49 -0000 1.18 +++ usr.bin/truss/alpha-fbsd.c 15 Sep 2004 01:20:57 -0000 @@ -161,8 +161,7 @@ if (fsc.name && (trussinfo->flags & FOLLOWFORKS) && ((!strcmp(fsc.name, "fork") - || !strcmp(fsc.name, "rfork") - || !strcmp(fsc.name, "vfork")))) + || !strcmp(fsc.name, "rfork")))) { trussinfo->in_fork = 1; } Index: usr.bin/truss/amd64-fbsd.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/amd64-fbsd.c,v retrieving revision 1.3 diff -u -u -r1.3 amd64-fbsd.c --- usr.bin/truss/amd64-fbsd.c 17 Jul 2004 19:48:49 -0000 1.3 +++ usr.bin/truss/amd64-fbsd.c 15 Sep 2004 01:20:57 -0000 @@ -160,8 +160,7 @@ if (fsc.name && (trussinfo->flags & FOLLOWFORKS) && ((!strcmp(fsc.name, "fork") - || !strcmp(fsc.name, "rfork") - || !strcmp(fsc.name, "vfork")))) + || !strcmp(fsc.name, "rfork")))) { trussinfo->in_fork = 1; } Index: usr.bin/truss/i386-fbsd.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/i386-fbsd.c,v retrieving revision 1.23 diff -u -u -r1.23 i386-fbsd.c --- usr.bin/truss/i386-fbsd.c 8 Aug 2004 23:29:36 -0000 1.23 +++ usr.bin/truss/i386-fbsd.c 15 Sep 2004 01:20:57 -0000 @@ -166,8 +166,7 @@ if (fsc.name && (trussinfo->flags & FOLLOWFORKS) && ((!strcmp(fsc.name, "fork") - || !strcmp(fsc.name, "rfork") - || !strcmp(fsc.name, "vfork")))) + || !strcmp(fsc.name, "rfork")))) { trussinfo->in_fork = 1; } Index: usr.bin/truss/i386-linux.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/i386-linux.c,v retrieving revision 1.23 diff -u -u -r1.23 i386-linux.c --- usr.bin/truss/i386-linux.c 17 Jul 2004 19:48:49 -0000 1.23 +++ usr.bin/truss/i386-linux.c 15 Sep 2004 01:20:57 -0000 @@ -140,8 +140,7 @@ } if (fsc.name && (trussinfo->flags & FOLLOWFORKS) - && ((!strcmp(fsc.name, "linux_fork") - || !strcmp(fsc.name, "linux_vfork")))) + && (!strcmp(fsc.name, "linux_fork"))) { trussinfo->in_fork = 1; } Index: usr.bin/truss/ia64-fbsd.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/ia64-fbsd.c,v retrieving revision 1.7 diff -u -u -r1.7 ia64-fbsd.c --- usr.bin/truss/ia64-fbsd.c 17 Jul 2004 19:48:49 -0000 1.7 +++ usr.bin/truss/ia64-fbsd.c 15 Sep 2004 01:20:57 -0000 @@ -155,8 +155,7 @@ if (fsc.name && (trussinfo->flags & FOLLOWFORKS) && ((!strcmp(fsc.name, "fork") - || !strcmp(fsc.name, "rfork") - || !strcmp(fsc.name, "vfork")))) + || !strcmp(fsc.name, "rfork")))) { trussinfo->in_fork = 1; } Index: usr.bin/truss/main.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/main.c,v retrieving revision 1.38 diff -u -u -r1.38 main.c --- usr.bin/truss/main.c 17 Jul 2004 19:19:36 -0000 1.38 +++ usr.bin/truss/main.c 15 Sep 2004 01:20:57 -0000 @@ -43,6 +43,7 @@ #include <sys/pioctl.h> #include <sys/types.h> #include <sys/time.h> +#include <sys/wait.h> #include <sys/resource.h> #include <ctype.h> @@ -243,7 +244,8 @@ START_TRACE: Procfd = start_tracing( - trussinfo->pid, S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT | + trussinfo->pid, + S_EXEC | S_SCE | S_SCX | S_CORE | S_EXIT | S_FWAIT | ((trussinfo->flags & NOSIGS) ? 0 : S_SIG), ((trussinfo->flags & FOLLOWFORKS) ? PF_FORK : 0)); if (Procfd == -1) @@ -303,6 +305,19 @@ } funcs->exit_syscall(trussinfo, pfs.val); break; + case S_FWAIT: + if (trussinfo->flags & FOLLOWFORKS) { + /* Fork ourself to trace child */ + int forkpid = fork(); + if (forkpid == 0) { + /* Child truss starts tracing */ + trussinfo->pid = pfs.val; + goto START_TRACE; + } + /* Parent truss waits for child (so output prints in right order) */ + waitpid(forkpid, NULL, 0); + } + break; case S_SIG: signame = strsig(pfs.val); fprintf(trussinfo->outfile, "SIGNAL %lu (%s)\n", pfs.val, Index: usr.bin/truss/sparc64-fbsd.c =================================================================== RCS file: /home/ncvs/FreeBSD/src/usr.bin/truss/sparc64-fbsd.c,v retrieving revision 1.7 diff -u -u -r1.7 sparc64-fbsd.c --- usr.bin/truss/sparc64-fbsd.c 17 Jul 2004 19:48:49 -0000 1.7 +++ usr.bin/truss/sparc64-fbsd.c 15 Sep 2004 01:20:57 -0000 @@ -162,8 +162,7 @@ if (fsc.name && (trussinfo->flags & FOLLOWFORKS) && ((!strcmp(fsc.name, "fork") - || !strcmp(fsc.name, "rfork") - || !strcmp(fsc.name, "vfork")))) + || !strcmp(fsc.name, "rfork")))) { trussinfo->in_fork = 1; } --- truss-patch ends here --- >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040915014625.2D021AAF>