[MLton-user] Re: fork() in MLton on Cygwin

Stephen Weeks sweeks@sweeks.com
Mon, 12 Jul 2004 18:04:48 -0700


> After changing gc.c and process.sml, I found the following changes
> in the regression suite:
...
> socket.sml:
> Used to fail on fork(), now fork() "works" but fails when parent
> attempts Socket.connect()

This is probably OK.  We have seen the same difference on OpenBSD.  It
is due to different treatment of connecting to a socket before an
accept has been done.  See

	http://www.mlton.org/pipermail/mlton/2004-June/015893.html

> textio.2.sml:
> Doesn't use fork(), fails because of how read() handles '\r'

This is OK.  It is a known regression difference on Cygwin.

> world{1..5}.sml:
> Used to fail on fork, now fork() "works" but fails during exec()
>
> I haven't debugged the world?.sml tests thoroughly, but I have found
> that the following work:
> 
> -a program that forks and execs
> 
> -saving the world and then loading it from the shell
> (./foo @MLton load-world /tmp/world --)
>
> -a program that saves the world, forks and the parent loads the
> saved world
>
> -a program that saves the world, forks and the child loads the saved
> world using a C wrapper for exec

Hmm.  I'm not sure how this is different than what world1.sml does.
Looking at basis-library/mlton/world.sml, MLton.World.load is
implemented by making a C call to exec.

> So the problem seems to be specific to how save/load
> and fork/exec interact.

Yes.  This sounds like exactly the same kind of problem I used to have
with Cygwin where it didn't do copy-on-write correctly and the child
process didn't get a private copy of the address space.  You might be
able to distill from what MLton is doing a pure C example of what's
going wrong.  Also, strace could be helpful.

> Besides gc.c, is there any other place where Windows functions might
> need to be replaced with Cygwin functions?

Not that I can think of.

> Is there anything special about MLton.World.save that affects the
> virtual address space?

The C code for load/save world is defined in runtime/gc.c, in
loadWorld() and GC_saveWorld().  They both do address space stuff;
GC_saveWorld because it does a gc and loadWorld because it has to
allocate the heap for the world.