Sunday, June 29, 2008

OCaml's Unix module and ARGV

Be warned: the string array argument to Unix.create_process et al. represents the entire argument vector: the first element should be the command name. I didn't expect this, since there is a separate prog argument to create_process, and ended up with weird behavior* like,

# open Unix;;
# create_process "sleep" [|"10"|] stdin stdout stderr;;
10: missing operand
Try `10 --help' for more information.
- : int = 22513

This can be a bit insidious—in many cases skipping the first argument will only subtly change the behavior of the child process.

Note that the prog argument is what matters in terms of invoking the sub-process---the first element of the argument vector is what just what is passed into the process. Hence,

# create_process "gcc" [|"foo";"--version"|] stdin stdout stderr;;
- : int = 24364
foo (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu7)

* Actually, this "weird behavior" is the test that finally made me realize what was going on. The emergent behavior of my app was much more mysterious...


Vasilis said...
This comment has been removed by the author.
Vasilis said...

It is a bit weird, but it just follows the behaviour of the system call actually used. execvp(2) and related functions expect the command name as the first argument:

char *args = { prg_name, arg1, NULL };
execvp(prg_name, args);

I guess it affects the program called only if it reads argv.

David Teller said...

I concur that the design of the Unix module is quite low-level. I belive a higher-level module would be quite useful for the community -- in particular, at some point, we're going to start looking for such a module for Batteries Included.

Chris said...

vasilis, I'm sure you're right about *why* it's this way, but: (a) the Unix module has an execvp function, create_process is supposed to be "high level", and (b) this pre-condition ought to be documented somewhere, for the benefit of those who aren't familiar with the standard Unix exec functions.

david teller, good luck.