shithub: mc

Download patch

ref: 9a388068afc910ad273cb32a983f7cd4ed6c6f51
parent: 32048b6b17efd288f303045e3d1417ca21c39901
author: Ori Bernstein <[email protected]>
date: Thu Jan 9 16:19:32 EST 2014

Fix fork on osx

    fork() has a funky ABI, and you need to check %edx to know
    if you're the parent or child, and clear the PID in userspace.

--- a/libstd/sys-osx.myr
+++ b/libstd/sys-osx.myr
@@ -531,14 +531,16 @@
 	const sysctl	: (mib : int[:], old : byte[:]#, new : byte[:] -> int)
 ;;
 
+extern const __osx_fork : (->int64)
+
 /* process control */
 const exit	= {status;		syscall(Sysexit, status castto(int64))}
 const getpid	= {;			-> syscall(Sysgetpid, 1)}
 const kill	= {pid, sig;		-> syscall(Syskill, pid, sig)}
-const fork	= {;			-> syscall(Sysfork)}
+const fork	= {;			-> __osx_fork()}
 const wait4	= {pid, loc, opt, usage;	-> syscall(Syswait4, pid, loc, opt, usage)}
 const waitpid	= {pid, loc, opt;
-	-> wait4(pid, loc, opt, 0 castto(byte#)) 
+	-> wait4(pid, loc, opt, 0 castto(rusage#)) 
 }
 
 const execv	= {cmd, args
--- a/libstd/syscall-osx.s
+++ b/libstd/syscall-osx.s
@@ -23,3 +23,30 @@
 success:
 	popq %rbp
 	ret
+
+/*
+ * OSX is dumb about fork, and needs an assembly wrapper.
+ * The fork() syscall, when called directly, returns the pid in both
+ * processes, which means that both parent and child think they're
+ * the parent.
+ *
+ * checking this involves peeking in %edx, so we need to do this in asm.
+ */
+.globl _std$__osx_fork
+_std$__osx_fork:
+	pushq %rbp
+
+	movq $0x2000002,%rax
+	syscall
+
+	jae forksuccess
+	negq %rax
+
+forksuccess:
+	testl %edx,%edx
+	jz isparent
+	xorq %rax,%rax
+isparent:
+	popq %rbp
+	ret
+