My sample code is the following. This uses boost.process v2
#include <boost/filesystem.hpp>
#include <boost/process/v2.hpp>
#include <boost/asio.hpp>
namespace sys = boost::system;
namespace v2 = boost::process::v2;
namespace fs = boost::filesystem;
namespace asio = boost::asio;
using launcher_type = v2::posix::default_launcher;
using pathname_type = fs::path;
using args_type = char* const*;
const fs::path null_cmd = v2::environment::find_executable("true");
std::initializer_list<std::string> args{};
size_t last_local_event = 0;
struct hooks {
sys::error_code on_setup(launcher_type &, const pathname_type &, const args_type &) {
last_local_event = 1;
return sys::error_code{};
}
};
auto main() -> int {
asio::io_context context;
sys::error_code ec{};
launcher_type launch{};
hooks init{};
v2::process p = launch(
context, ec,
null_cmd,
args,
std::move(init)
);
context.run();
p.wait(ec);
assert(last_local_event == 1);
}
The custom on_setup
callback in my hooks
instance is not being applied under the boost process launcher
instance, a v2::posix::default_launcher
.
It looks like the function signature for my on_setup
call should match that for an on_setup
callback under a boost process Linux launcher of this launcher type.
After taking a look at the boost.process source code, I believe that my on_setup
call should be substituted and called during launcher on_setup
, as it was provided via the initializer init
when the process launcher object was called.
I believe that the function signature for my on_setup
function matches that expected for on_setup
with a custom initializer in boost process on Linux. The function signatures appear to match, and yet my custom initializer is not being used for the process. The assert
call fails in my example code. The value of last_local_event
was not changed by my custom on_setup
function.
Is there something I'm missing here, such as in how to apply the template substitutions for a custom boost.process on_setup
hook?
Could there be any advice on how to diagnose why my hooks::on_setup
is not being called from the provided init
?
I've tested this under compilation with clang20 using C++20 and with GCC 13.2.0 using C++2b(GNU)
Under local build, maybe I've been missing some compiler notices due to including boost with -isystem
. The compiler might provide some info about why the substitution is not working out there?
The substitution may have been failing on the args_type as defined
using args_type = char* const*;
as used within the method
sys::error_code on_setup(launcher_type &, const pathname_type &, const args_type &)
When using similar code (adapted after a unit test in boost process) but when specializing on_setup
as so, then the launcher-initializer's on_setup
method is reached as expected:
struct hooks {
// [sic]
template <typename L>
sys::error_code on_setup(L&, const pathname_type&, const char*const*&) {
event_flag = true;
return sys::error_code{};
}
};
This also works, though it may be a little less portable, when defining the on_setup
hook without a template for the launcher arg:
struct hooks {
// [sic]
sys::error_code on_setup(launcher_type&, const pathname_type&, const char*const*&) {
event_flag = true;
return sys::error_code{};
}
};
The args type for boost process v2 on posix-like platforms is char* const*
. This differs to windows platforms, which would use std::wstring
as the args type.
Why does the template substitution fail when using my args_type
specialization there? This was tested with both GCC and clang. It seems const args_type&
in the method declaration is handled as a different type than const char*const*&
?
I understand that I can probably work around this by using a macro defined on each platform, or folding the initial const
into the args_type
definition, to keep it platform-generic in some way, e.g
using const_args_type = const char* const*;
Can anyone help to elucidate why the template substitution fails when on_setup
is defined with const args_type&
there? Could it be anything specific to C-like array types?
args_type
is not a pointer-to-pointer to CONST char.
using args_type = char* const*;
Should be
using args_type = char const* const*;
That fixes it
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
#include <boost/process/v2.hpp>
namespace sys = boost::system;
namespace bp = boost::process::v2;
namespace fs = boost::filesystem;
namespace asio = boost::asio;
using launcher_type = bp::posix::default_launcher;
using pathname_type = fs::path;
fs::path const null_cmd = bp::environment::find_executable("true");
std::initializer_list<std::string> args{};
size_t last_local_event = 0;
struct hooks {
using args_type = char const* const*;
sys::error_code on_setup(launcher_type&, pathname_type const&, args_type const&) const {
last_local_event = 1;
return {};
}
};
int main() {
asio::io_context context;
sys::error_code ec{};
launcher_type launch{};
hooks init{};
bp::process p = launch(context, ec, null_cmd, args, std::move(init));
context.run();
p.wait(ec);
assert(last_local_event == 1);
}