Fix vfork-by-clone tracing (on ia64)

Jan Kratochvil jan.kratochvil at redhat.com
Tue Jul 8 18:07:07 UTC 2008


On Tue, 01 Jul 2008 00:45:43 +0200, Dmitry V. Levin wrote:
> I still do not fully understand why strace may hang in this case.

This is nothing special on ia64, just the syscall number is different there.
You can simulate the current ia64 vfork() bug on x86 by the attached patch.

The native vfork() (or CLONE_VFORK) syscall will hang the parent execution
until the child will do execve() or _exit().  Unfortunately strace on fork
hangs unidentified children appearing by WAITPID - code around the line:
Process %d attached (waiting for parent)\n",
as it expects to see the new PID as a result from a fork() syscall of the
parent (it does use neither PTRACE_GETEVENTMSG nor /proc/PID/stat* scanning to
find the parent PID).

But the parent got blocked by the native kernel until the child execve()s or
_exit()s and strace blocked the child until the parent returns from fork().
=> deadlock


> > +		/* ia64 calls directly `clone (CLONE_VFORK)' contrary to x86
> > +		   SYS_vfork above.  Even on x86 we turn the VFORK semantics
> > +		   into plain FORK - each application must not depend on the
> > +		   VFORK specifics according to POSIX.  We would hang waiting
> > +		   for the parent resume otherwise.  */

> We already change vfork() to fork() in followvfork mode, so changing
> clone() this way is probably acceptable here, too.  I'm not sure, though.

Yes, while it is wrong it already happens on x86 so why not on ia64.
It is not a regression, it is still an improvement.


Regards,
Jan
-------------- next part --------------
--- util.c	20 May 2008 00:34:34 -0000	1.75
+++ util.c	8 Jul 2008 17:56:47 -0000
@@ -1281,6 +1281,9 @@ struct tcb *tcp;
 #ifndef CLONE_PTRACE
 # define CLONE_PTRACE    0x00002000
 #endif
+#ifndef CLONE_VFORK
+# define CLONE_VFORK     0x00004000
+#endif
 #ifndef CLONE_STOPPED
 # define CLONE_STOPPED   0x02000000
 #endif
@@ -1510,7 +1513,8 @@ struct tcb *tcp;
 		    || get_arg0 (tcp, &state, &tcp->inst[0]) < 0
 		    || get_arg1 (tcp, &state, &tcp->inst[1]) < 0
 		    || change_syscall(tcp, clone_scno[current_personality]) < 0
-		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD) < 0
+		    || set_arg0 (tcp, &state, CLONE_PTRACE|SIGCHLD
+			 | (known_scno(tcp) == SYS_vfork ? CLONE_VFORK : 0)) < 0
 		    || set_arg1 (tcp, &state, 0) < 0
 		    || arg_finish_change (tcp, &state) < 0)
 			return -1;


More information about the Strace-devel mailing list