On Tue, 11 May 2010, David Matthews wrote:

Michael Norrish wrote:
Incidentally, on the machine where Posix.Process.exec("/bin/ls", []) seg. faults, Unix.execute("/bin/ls", []) works correctly. The Basis library documentation I have for the Unix structure doesn't discuss how the argv component should be setup, but attempting

  Unix.execute("/bin/ls", ["ls"])

prompts a message from ls saying that there is no file called ls.

This doesn't seem consistent.

Curiously, on the Macbook where Posix.Process.exec gives ENOTSUP, Unix.execute does work.

It turns out that on Mac OS X execv returns ENOTSUP if the process is multi-threaded. You need to use Posix.Process.fork first to start a new process:
case Posix.Process.fork() of
  SOME _ => OS.Process.exit OS.Process.success
| NONE => Posix.Process.exec("/bin/ls", ["ls"]);

This isn't documented in Apple's man page for execv and I found the explanation at
http://factor-language.blogspot.com/2007/07/execve-returning-enotsup-on-mac-os-x.html

The arguments for Posix.Process.exec and Unix.execute are different. The basis library book (Ganser and Reppy 2004) says for Unix.execute "execute(cmd, args) asks the operating system to execute the program named by the string cmd with the argument list args."

For Posix.Process.exec it says "The args argument is a list of string arguments to be passed to the new program. By convention, the first item in args is some form of the filename of the new program, usually the last arc in the path or filename." Like any informal specification this is subject to interpretation but I think the current behaviour conforms to this definition.

Since these are once again the typical multi-platform issues that I know only too well, I would like to point out how it is done in Isabelle/ML: http://isabelle.in.tum.de/repos/isabelle/file/Isabelle2009-1/src/Pure/ML-Systems/multithreading_polyml.ML#l159

The code might look scary, but it works well on Linux, Mac OS, Cygwin, which are the three official platform families supported by Isabelle. Extra complexitiy is caused by our multithreading setup, because several ML threads could invoke external processes independently, and we expect internal Thread.interrupt propagation, just as for any other ML execution.


Multiplatform support essentially works by ignoring official "standards", but use things that are known to behave uniformly on all systems:

  * OS.Process.system which David has adjusted at some point to prevent
    surprises with fork/exec on the windows platform, which would
    otherwise copy the whole process memory space.

  * Perl plumbing to get nested process groups right, to allow
    signals sent to sub-shell scripts, pipes etc.

  * GNU bash to escape from the unknown standard /bin/sh --
    there are many different versions of that on different systems, and
    they hardly agree on essentials like signal propagation.

Thus Isabelle/ML users can do strange things reliably, e.g. on Cygwin invoke system "notepad.exe" from an ML thread with some ML timout wrapping, and still get the expected behaviour:

  ML> TimeLimit.timeLimit (Time.fromSeconds 3) system "notepad.exe";
  Exception- TimeOut raised

Here is another example:

  ML> val x = Future.fork (fn () => system "notepad.exe");
  ML> Future.cancel x;


        Makarius
_______________________________________________
polyml mailing list
polyml@inf.ed.ac.uk
http://lists.inf.ed.ac.uk/mailman/listinfo/polyml

Reply via email to