[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.