Boost logo

Boost :

Subject: Re: [boost] Boost.Process article: Tutorial and request for comments
From: Boris Schaeling (boris_at_[hidden])
Date: 2009-04-25 08:52:24


On Tue, 21 Apr 2009 20:15:11 +0200, Phil Endecott
<spam_from_boost_dev_at_[hidden]> wrote:

> [...]First a general comment about how I would prefer that portable
> system API wrappers are implemented. No doubt other would have
> different views. Ideally, I'd like to see separate thin wrappers for
> Windows and POSIX that just "C++-ify" those APIs. Then on top of that
> implement a portability layer. My reason is this: I rarely if ever care
> about Windows and I already know how the POSIX APIs work (i.e. what the
> functions are called and what the semantics are). So please don't hide
> the bottom level thin wrappers that you must have as an implementation
> detail.

I see. It reminds me a bit of the free-standing functions in
Boost.Filesystem which I think simply call POSIX and Windows API
functions? I'm not sure though if I can work on such a layer - I hardly
have time to work on the upper layer. :-/

> Re the environment: I'm not enthusiastic that you have copied the
> environment into your own data structure. Why can't your environment
> type just wrap getenv() and setenv()? i.e.

Before I answer your questions I should note that I did not design
Boost.Process. I went through the entire code last year to make sure that
what we have works (fixing countless bugs and testing the library with
numerous compilers and platforms). I try to answer your questions as far
as I understand the rationale of the design.

> class environment {
> struct env_var_proxy {
> const char* varname;
> env_var_proxy(const char* varname_): varname(varname_) {}
> operator const char*() const { return getenv(varname); }
> void operator=(const char* newval) { setenv(varname,newval,1); }
> }

The type environment is also used to setup a new environment for a child
process, eg.:

context ctx;
ctx.environment.insert(environment::value_type("PATH", "/newpath"));
launch(..., ctx);

> [...]This example code:
>
> std::string exec = find_executable_in_path("notepad.exe");
> std::vector<std::string> args = boost::assign::list_of("notepad.exe");
> context ctx;
> ctx.environment = self::get_environment();
> launch(exec, args, ctx);
>
> Is actually more verbose than directly calling the POSIX functions:
>
> int child_pid = fork();
> if (child_pid == -1) throw "fork failed";
> if (child_pid == 0) {
> execlp("notepad.exe","notepad.exe",NULL);
> _exit(1);
> }
>
> Why don't you boil it down to:
>
> launch_process("notepad.exe");

Currently the environment variables of the current process are not
automatically inherited by a child process. I agree that it should be
easier to launch a new process. But then environment variables should
probably be inherited by default?

> You write:
>
>> it is very important to refer to the executable with an absolute path -
>> on all platforms including POSIX systems
>
> Why do you say that?

It's a requirement of Boost.Process. It doesn't need to be an absolute
path but can also be a relative path of course. What's not guaranteed
though is that an executable is automatically found when only a filename
is given. There is a function which searches for an executable and returns
an absolute path. Would you like to see Boost.Process search for an
executable automatically?

> It's not clear to me if your terminate() calls wait() or not. Beware of
> processes that ignore SIGCHLD.

Currently terminate() only calls kill().

>> 3) Currently Boost.Process is really only useful for creating child
>> processes. It's not possible for example to detect and iterate over
>> other
>> processes on a system. I guess Boost.Process should be enhanced here.
>> Then
>> one day the well-known utility 'ps' on POSIX systems could be
>> implemented
>> in Boost C++. Any comments?
>
> What is the use case for this?

I asked myself the other way round: Why should a library for process
management only support child processes? But I'd agree that accessing
other processes has a lower priority.

> [...]
>> 8) There is a method wait() which makes it possible to wait for another
>> process to exit. Currently wait() is provided by the class child though.
>> Shouldn't it really be defined by the class process (so you can wait not
>> only for child processes to exit)?
>
> Are you certain that wait() can be used to monitor non-child processes?
> I don't believe that it can.

Hm, on POSIX systems it doesn't work but on Windows it works. Another
problem to think about.

Boris


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk