Fix vfork-by-clone tracing (on ia64)

Jan Kratochvil jan.kratochvil at redhat.com
Mon Jun 30 13:25:58 UTC 2008


Hi,

this testcase hangs on ia64:

$ echo 'int main () { return vfork (); }' >vfork.c; gcc -o vfork vfork.c; strace -f ./vfork
execve("./vfork", ["./vfork"], [/* 41 vars */]) = 1
...
clone(Process 2929 attached (waiting for parent)

Fix tested on RHEL-5 kernel-2.6.18-94.el5.ia64.  Older kernels (such as
kernel-2.6.18-53.el5.ia64) do not hang as they have a bug causing strace not
tracing the children (as strace is unable to force CLONE_PTRACE there).
Sorry for no ia64 vanilla kernels testing.


Regards,
Jan
-------------- next part --------------
2008-06-27  Jan Kratochvil  <jan.kratochvil at redhat.com>

	* util.c (CLONE_VFORK): Define if not defined already.
	(setbpt): Clear CLONE_VFORK for SYS_CLONE and SYS_CLONE2.  New comment.
	Originally found by Vitaly Mayatskikh.

--- util.c	20 May 2008 00:34:34 -0000	1.75
+++ util.c	30 Jun 2008 12:53:31 -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
@@ -1524,12 +1527,17 @@ struct tcb *tcp;
 #ifdef SYS_clone2
 	case SYS_clone2:
 #endif
-		if ((tcp->u_arg[arg0_index] & CLONE_PTRACE) == 0
-		    && (arg_setup (tcp, &state) < 0
-			|| set_arg0 (tcp, &state,
-				     tcp->u_arg[arg0_index] | CLONE_PTRACE) < 0
-			|| arg_finish_change (tcp, &state) < 0))
-			return -1;
+		/* 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.  */
+		if ((arg_setup (tcp, &state) < 0
+		    || set_arg0 (tcp, &state,
+				 (tcp->u_arg[arg0_index] | CLONE_PTRACE)
+				 & ~CLONE_VFORK) < 0
+		    || arg_finish_change (tcp, &state) < 0))
+		    return -1;
 		tcp->flags |= TCB_BPTSET;
 		tcp->inst[0] = tcp->u_arg[arg0_index];
 		tcp->inst[1] = tcp->u_arg[arg1_index];


More information about the Strace-devel mailing list