|
Boost : |
Subject: Re: [boost] [boost.process] 0.6 Redesign
From: Raphaël Londeix (raphael.londeix_at_[hidden])
Date: 2016-04-20 11:50:28
Hi,
Of course you can implement the example above very easily with the process
> library:
>
Thanks, that's almost what I need, but it is not practical for stream
initializations:
enum stream { std_in, std_out, std_err, dev_null };
struct options
{
// stderr redirection
boost::variant<
boost::filesystem::path,
boost::process::pipe,
stream> err;
...
};
How can I spawn a process, so that it will redirect stderr alternatively to
a path, to a pipe, to stdout, or to /dev/null ? If I'm right, I will need
to write explicitly 4 different calls to process::execute(). And it gets
worse if we want to have the same flexibility for the stdin and stdout ...
All in all, I'm not suggesting that you add support for boost::variant, but
instead suggesting that boost.process could have one low-level generic way
to spawn a process. As mentioned earlier, the Python subprocess library is
great, its subprocess.Popen[1] constructor provides a way to do so.
BUT you can also use a functional style if you want to:
> auto in_setting = process::std_in < null;
> auto c = execute("thingy", in_setting);
>
I'm not suggesting that you should remove the nice API, more that it could
be optional.
> you have a few settings which will be aggregated like environment
settings or args.
>
Yes, sorry, I didn't spot that for the env and args. However the argument
remains for the streams initialization.
The Problem with [2] and [3] is, that I now have the
> initializer-sequence as a template parameter of the executor. I did this
> so initializers can access the sequence, which was necessary for the
> async stuff (i.e. so they can access the io_service).
AFAIK, this was also the case in the 0.5 version
> This renders any virtualization impossible, because the handler-functions
> now have to be
> tempalted.
>
Yes.
> Also: though not yet implemented, I'd like to have a few compile-time
> checks, e.g. that you don't redirect a pipe twice etc. That would be
> completely impossible with a initializer sequence built at runtime.
>
I believe that those checks are incredibly cheap compared to a fork or a
CreateProcess(), why not also do some runtime checks ?
> Now: since we have a finite amount of initializers, it would be possible
> to implement some polymorphic sequence with boost.variant, but I still
> fail to see why that must be determined at runtime. Keep in mind: you
> would not determine the value of some initializer but which initializers
> you set. Do you have an example where it has to be done at runtime? That
> maybe helpful for me to understand the actual problem here. I really
> don't like to use runtime-polymorphy when it can be done
at compile-time
I completely agree that compile-time checks are nice, but having a lower
level non fully typesafe API cannot hurt.
An example where it is necessary to do the initialization at runtime could
be a simple launcher that can exercise every combination of options that
boost.process allow, like:
Usage: boost-process-launcher [OPTIONS] -- COMMAND [ARG]...
That you could use like that
$ echo test | boost-process-launcher --stdout=STDERR
--stderr=./somefile.txt --E ENVVAR=1 --no-inherit-env -- grep test
Cheers,
[1] https://docs.python.org/3.6/library/subprocess.html#popen-constructor
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk