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