On Wed, 12 May 2010, Michael Norrish wrote:

Cygwin is not really relevant, but I suppose that, out of idle curiosity, it would nice to know if Posix.Process.exec worked there.

I have checked the (long) mail exchange with David from 2 years ago, when we sorted out many issues to make it work the way it is in Isabelle2008 or later, until today.

Attached is an earlier experiment involving straight-forward fork/exec with join/kill operations. Here is an example on Cygwin:

  ML> elapsed_time (fn () => join (fork "true")) ();
  0.719

That's almost a second penalty. The delay depends on various factors, including the size of the running ML process. The best I can get here is approx. 0.4 seconds.

On Linux on the same hardware class the result is like that:

  ML> elapsed_time (fn () => join (fork "true")) ();
  0.102

These 100ms are somehow intrinsic to the way the Poly/ML runtime system invokes external processes. David can explain that better. (I wonder if the builtin delay loop is still required these days.)


        Makarius
fun elapsed_time f x =
  let
    val now = Time.now ();
    val res = f x;
    val _ = TextIO.output (TextIO.stdOut, Time.toString (Time.now () - now) ^ 
"\n");
  in res end;

fun fork cmdline =
  let
    val _ = TextIO.flushOut TextIO.stdOut;
    val {infd = in1, outfd = out1} = Posix.IO.pipe ();
    val {infd = in2, outfd = out2} = Posix.IO.pipe ();
  in
    (case Posix.Process.fork () of
      SOME pid =>
       (Posix.IO.close in1;
        Posix.IO.close out2;
        {pid = pid, stdin = out1, stdout = in2})
    | NONE =>
       (Posix.IO.close out1;
        Posix.IO.close in2;
        Posix.IO.dup2 {old = in1, new = Posix.FileSys.wordToFD 0w0};
        Posix.IO.dup2 {old = out2, new = Posix.FileSys.wordToFD 0w1};
        Posix.IO.close in1;
        Posix.IO.close out2;
        Posix.Process.execp ("bash", ["bash", "-c", cmdline]);
        OS.Process.terminate OS.Process.failure)
       handle _ => OS.Process.terminate OS.Process.failure)
  end;

fun join {pid, stdin, stdout} =
  let
    val _ = Posix.IO.close stdin;
    val _ = Posix.IO.close stdout;
    fun wait () =
      (case #2 (Posix.Process.waitpid (Posix.Process.W_CHILD pid, [])) of
        Posix.Process.W_STOPPED _ => wait ()
      | status => status);
  in
    (case wait () of
      Posix.Process.W_EXITED => 0
    | Posix.Process.W_EXITSTATUS 0wx82 => raise SML90.Interrupt
    | Posix.Process.W_EXITSTATUS w => Word8.toInt w
    | Posix.Process.W_SIGNALED s =>
        if s = Posix.Signal.int then raise SML90.Interrupt
        else 256 + LargeWord.toInt (Posix.Signal.toWord s))
  end;

fun kill {pid, stdin, stdout} =
  Posix.Process.kill (Posix.Process.K_PROC pid, Posix.Signal.int);

_______________________________________________
polyml mailing list
[email protected]
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml

Reply via email to