The documentation boost doesn't provide any example for creating a child process with a custom environment using process::child(...)
.
An example is given with process::system(...)
but the function system
has less possible operations (such as pipes or waitpid) so I would like to have a full example using process::child
if possible.
Asked
Active
Viewed 3,020 times
5

xaxxon
- 19,189
- 5
- 50
- 80

zack evein
- 279
- 5
- 13
2 Answers
4
The last answer and comment are quite old but I can confirm that boost::process::child
with environment parameter works using Boost version 1.65 under Ubuntu 18.04. The documentation about that is quite thin, so I had to find out by myself:
std::string command = "/usr/bin/something";
ipstream pipe_stream;
// Get current env
auto env = boost::this_process::environment();
// Add something
env["CHINESE_FOOD"] = "GOOD";
// Change something
env["CHINESE_FOOD"] = "GREAT";
// Delete something
env["CHINESE_FOOD"].clear();
boost::process::child childProc(command, env, std_out > pipe_stream);
And of course, if environment is not needed, it will inherit from parent process automatically
std::string command = "/usr/bin/something";
ipstream pipe_stream;
boost::process::child childProc(command, std_out > pipe_stream);

Serge Grondin
- 51
- 3
-
For some reason on Linux (CentOS 7) passing a boost::this_process::environment object to boost::process::child constructor also changes the environment of the parent process. Is this intended? – Ivan_a_bit_Ukrainivan Jan 20 '22 at 12:24
-
You are right, according to Boost documentation my last exemple will modify the current process environment. The correct way here would have been: ` // Get current env auto env = boost::this_process::environment(); // Copy it into an environment separate to the one of this process boost::process::environment envChild = env; // Add something envChild["CHINESE_FOOD"] = "GOOD"; // Change something envChild["CHINESE_FOOD"] = "GREAT"; // Delete something envChild["CHINESE_FOOD"].clear(); boost::process::child childProc(command, envChild, std_out > pipe_stream);` – Serge Grondin Jan 21 '22 at 13:18
-
You can also declare an empty environment instead of taking the one from the process `boost::process::environment env;` – Serge Grondin Jan 21 '22 at 13:29
-
ahh... Yes! My mistake was that I had wrong assumption about `boost::process::native_environment` type. I had to copy it to `boost::process::environment` and further modify it. `boost::process::native_environment` is a copyable accessor object! – Ivan_a_bit_Ukrainivan Jan 28 '22 at 10:55
0
in system.hpp, system_impl, which supports custom env, is implemented in terms of child,
template<typename IoService, typename ...Args>
inline int system_impl(
std::true_type, /*needs ios*/
std::true_type, /*has io_context*/
Args && ...args)
{
IoService & ios = ::boost::process::detail::get_io_context_var(args...);
system_impl_success_check check;
std::atomic_bool exited{false};
child c(std::forward<Args>(args)...,
check,
::boost::process::on_exit(
[&](int, const std::error_code&)
{
ios.post([&]{exited.store(true);});
}));
if (!c.valid() || !check.succeeded)
return -1;
while (!exited.load())
ios.poll();
return c.exit_code();
}
So the call to system from the docs:
bp::system("stuff", bp::env["VALUE_1"]="foo", bp::env["VALUE_2"]+={"bar1", "bar2"});
which calls:
template<typename ...Args>
inline int system(Args && ...args)
{
typedef typename ::boost::process::detail::needs_io_context<Args...>::type
need_ios;
typedef typename ::boost::process::detail::has_io_context<Args...>::type
has_ios;
return ::boost::process::detail::system_impl<boost::asio::io_context>(
need_ios(), has_ios(),
std::forward<Args>(args)...);
}
translates into this function, so you should be able to do the same.

xaxxon
- 19,189
- 5
- 50
- 80
-
apparently args are sent to `child` but it does not compile with child – zack evein Mar 09 '19 at 15:28