[MLton-user] cygwin fork?

Matthew Fluet fluet at tti-c.org
Tue Sep 25 06:37:31 PDT 2007


On Fri, 21 Sep 2007, Petersen, Leaf wrote:
> I just upgraded to the latest release of MLton, and simultaneously
> updated my cygwin to the latest version.  Some combination of the two
> seems to have resulted in fork no longer working.  In particular the
> following SML code
>
> val _ =
>    case Posix.Process.fork ()
>     of NONE =>
>        print "Child"
>      | SOME pid =>
>        print "Parent"
>
> produces the following output when compiled and run with mlton:
>
> unhandled exception: SysErr: Function not implemented [nosys]

I see this behavior as well on my Cygwin/Windows platform.

However, if I invoke the program with the 'use-mmap' runtime option
(./z @MLton use-mmap --), then the program behaves as expected.
Does using the 'use-mmap' runtime option work on your larger 
example/application?  If so, you can "bake-in" the runtime option by 
compiling your example/application with the '-runtime use-mmap' compiler 
option.

(One minor thing I noticed is that on Linux, the program always prints 
"Child" before "Parent", while on Cygwin/Windows, the order is pretty 
random.  I believe that both behaviors are within the spec for fork.)

> 1) There are several hints in the source and on the web that there are
> issues with fork.  However, in poking through the source, I couldn't
> figure out where this error was happening.  As far as I could tell, the
> C "fork" function is being eventually called, and presumably is
> returning ENOSYS.  And yet a similar C test program seems to work.  What
> am I missing?

You could try compiling with
   -const 'Exn.keepHistory true' -profile-include '\$\(SML_LIB\)'
to see a back-trace of where the exception is being raised.

I suspect that the ENOSYS is arising from the runtime system defaulting to 
the Windows API VirtualAlloc/VirtualFree for memory management, rather 
than the POSIX API mmap/free (provided by Cygwin).  I believe that Cygwin 
uses VirtualAlloc/VirtualFree to implement mmap/free, but it does so 
maintaining particular invariants.  Our use of VirtualAlloc/VirtualFree 
messes up those invariants, which I presume Cygwin is relying upon in 
order to properly copy the parent's memory to the child.

In the end, I suspect that we are being bitten by not using Cygwin as 
intended.  Cygwin gives a Unix-looking environment on Windows; it is 
working on the assumption that one is compiling Unix programs (which 
wouldn't normally call Windows API functions) on Windows.  Hence, it isn't 
surpising that calling Windows API functions (and, 
VirtualAlloc/VirtualFree is a particularly low-level function) can break 
the invariants that the Cygwin API is trying to maintain.

> 2) There are suggestions that using spawn is a good workaround.  This
> seems to work correctly for me.  However, I haven't figured out how to
> suppress stdin and stdout when using spawn as opposed to fork/exec.
> Anyone have experience with this?



More information about the MLton-user mailing list