diff --git a/include/boost/process/v2/detail/process_handle_signal.hpp b/include/boost/process/v2/detail/process_handle_signal.hpp index 3f8a26052..d8d355dfb 100644 --- a/include/boost/process/v2/detail/process_handle_signal.hpp +++ b/include/boost/process/v2/detail/process_handle_signal.hpp @@ -348,15 +348,17 @@ struct basic_process_handle_signal net::dispatch(exec, net::append(std::move(self), ec)); } #else - signal_set_dummy_ dummy_; - pid_t pid; + signal_set_dummy_ &handle; + pid_type pid_; + native_exit_code_type & exit_code; + template void operator()(Self &&self) { - auto exec = net::get_associated_immediate_executor(self, dummy_.get_executor()); + auto exec = net::get_associated_immediate_executor(self, handle.get_executor()); error_code ec; BOOST_PROCESS_V2_ASSIGN_EC(ec, net::error::operation_not_supported); - net::dispatch(exec, net::append(std::move(self), native_exit_code_type(), ec)); + net::dispatch(exec, net::append(std::move(self), ec)); } #endif template diff --git a/test/v2/CMakeLists.txt b/test/v2/CMakeLists.txt index 001e77e64..ed8e1f7d4 100644 --- a/test/v2/CMakeLists.txt +++ b/test/v2/CMakeLists.txt @@ -34,3 +34,14 @@ endfunction() boost_process_v2_test_with_target(process) boost_process_v2_test_with_target(ext) +boost_process_v2_test_with_target(disable_signalset) + +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + # The signal-based process handle that macOS and the BSDs use. + add_executable(boost_process_v2_disable_signalset_no_pidfd disable_signalset.cpp) + target_link_libraries(boost_process_v2_disable_signalset_no_pidfd PUBLIC Boost::process Boost::system Boost::filesystem boost_process_v2_test_impl) + target_compile_definitions(boost_process_v2_disable_signalset_no_pidfd PRIVATE BOOST_PROCESS_V2_DISABLE_PIDFD_OPEN=1) + add_dependencies(boost_process_v2_disable_signalset_no_pidfd boost_process_v2_test_target) + add_test(NAME boost_process_v2_disable_signalset_no_pidfd COMMAND $ + -- $) +endif() diff --git a/test/v2/Jamfile.jam b/test/v2/Jamfile.jam index e38452ce6..4027829a1 100644 --- a/test/v2/Jamfile.jam +++ b/test/v2/Jamfile.jam @@ -58,5 +58,8 @@ test-suite with_target : [ run process.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target ] [ run windows.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target : no windows:yes windows:Advapi32 ] [ run ext.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target : darwin:no ] + [ run disable_signalset.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target ] + [ run disable_signalset.cpp $(test_impl) : --log_level=all --catch_system_errors=no -- : target + : no linux:yes BOOST_PROCESS_V2_DISABLE_PIDFD_OPEN=1 : disable_signalset_no_pidfd ] ; diff --git a/test/v2/disable_signalset.cpp b/test/v2/disable_signalset.cpp new file mode 100644 index 000000000..c5b43e10f --- /dev/null +++ b/test/v2/disable_signalset.cpp @@ -0,0 +1,69 @@ +// Copyright (c) 2026 Stefan Dinkelacker +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Disable autolinking for unit tests. +#if !defined(BOOST_ALL_NO_LIB) +#define BOOST_ALL_NO_LIB 1 +#endif // !defined(BOOST_ALL_NO_LIB) + +// An application that handles SIGCHLD itself must keep asio from installing +// a handler for it. +#define BOOST_PROCESS_V2_DISABLE_SIGNALSET 1 + +#include + +#include +#include + +namespace bpv = boost::process::v2; +namespace asio = boost::asio; + +BOOST_AUTO_TEST_SUITE(disable_signalset); + +BOOST_AUTO_TEST_CASE(wait) +{ + using boost::unit_test::framework::master_test_suite; + const auto pth = master_test_suite().argv[1]; + + asio::io_context ctx; + BOOST_CHECK_EQUAL(bpv::process(ctx, pth, {"exit-code", "42"}).wait(), 42); +} + +BOOST_AUTO_TEST_CASE(async_wait) +{ + using boost::unit_test::framework::master_test_suite; + const auto pth = master_test_suite().argv[1]; + + asio::io_context ctx; + bpv::process proc(ctx, pth, {"exit-code", "42"}); + + bool called = false; + boost::system::error_code ec; + int code = -1; + + proc.async_wait( + [&](boost::system::error_code ec_, int code_) + { + called = true; + ec = ec_; + code = code_; + }); + + ctx.run(); + BOOST_CHECK(called); + +#if defined(BOOST_PROCESS_V2_WINDOWS) || defined(BOOST_PROCESS_V2_PIDFD_OPEN) \ + || defined(BOOST_PROCESS_V2_PDFORK) || defined(BOOST_PROCESS_V2_PIPEFORK) + // These handles wait on a handle or descriptor, which needs no signal set. + BOOST_CHECK_MESSAGE(!ec, ec.message()); + BOOST_CHECK_EQUAL(code, 42); +#else + // The signal-based handle has nothing to wait on, but wait() still works. + BOOST_CHECK_EQUAL(ec, asio::error::operation_not_supported); + BOOST_CHECK_EQUAL(proc.wait(), 42); +#endif +} + +BOOST_AUTO_TEST_SUITE_END();