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