diff --git a/include/boost/process/detail/posix/sigchld_service.hpp b/include/boost/process/detail/posix/sigchld_service.hpp index 4eb6de6cb..9d6640935 100644 --- a/include/boost/process/detail/posix/sigchld_service.hpp +++ b/include/boost/process/detail/posix/sigchld_service.hpp @@ -7,8 +7,11 @@ #ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ #define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ +#include #include #include +#include +#include #include #include #include @@ -26,6 +29,43 @@ class sigchld_service : public boost::asio::detail::service_base>> _receivers; inline void _handle_signal(const boost::system::error_code & ec); + + struct initiate_async_wait_op + { + sigchld_service * self; + template + void operator()(Initiation && init, ::pid_t pid) + { + // check if the child actually is running first + int status; + auto pid_res = ::waitpid(pid, &status, WNOHANG); + if (pid_res < 0) + { + auto ec = get_last_error(); + boost::asio::post( + self->_strand, + asio::append(std::forward(init), pid_res, ec)); + } + else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status))) + boost::asio::post( + self->_strand, + boost::asio::append(std::forward(init), status, std::error_code{})); + else //still running + { + sigchld_service * self_ = self; + if (self->_receivers.empty()) + self->_signal_set.async_wait( + boost::asio::bind_executor( + self->_strand, + [self_](const boost::system::error_code &ec, int) + { + self_->_handle_signal(ec); + })); + self->_receivers.emplace_back(pid, init); + } + } + }; + public: sigchld_service(boost::asio::io_context & io_context) : boost::asio::detail::service_base(io_context) @@ -37,47 +77,10 @@ class sigchld_service : public boost::asio::detail::service_base init{handler}; - - auto & h = init.completion_handler; - boost::asio::dispatch( - _strand, - [this, pid, h] - { - //check if the child actually is running first - int status; - auto pid_res = ::waitpid(pid, &status, WNOHANG); - if (pid_res < 0) - { - auto ec = get_last_error(); - boost::asio::post( - _strand, - [pid_res, ec, h] - { - h(pid_res, ec); - }); - } - else if ((pid_res == pid) && (WIFEXITED(status) || WIFSIGNALED(status))) - boost::asio::post( - _strand, - [status, h] - { - h(status, {}); //successfully exited already - }); - else //still running - { - if (_receivers.empty()) - _signal_set.async_wait( - [this](const boost::system::error_code &ec, int) - { - boost::asio::dispatch(_strand, [this, ec]{this->_handle_signal(ec);}); - }); - _receivers.emplace_back(pid, h); - } - }); - - return init.result.get(); + return boost::asio::async_initiate< + SignalHandler, + void(int, std::error_code)>( + initiate_async_wait_op{this}, handler, pid); } void shutdown() override { diff --git a/test/async_pipe.cpp b/test/async_pipe.cpp index 0507dbd7a..133c54175 100644 --- a/test/async_pipe.cpp +++ b/test/async_pipe.cpp @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(multithreaded_async_pipe) asio::io_context ioc; std::vector threads; - for (int i = 0; i < std::thread::hardware_concurrency(); i++) + for (auto i = 0u; i < std::thread::hardware_concurrency(); i++) { threads.emplace_back([&ioc] { diff --git a/test/group_wait.cpp b/test/group_wait.cpp index aa0d92586..91c96b5b3 100644 --- a/test/group_wait.cpp +++ b/test/group_wait.cpp @@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(wait_group_test, *boost::unit_test::timeout(5)) BOOST_CHECK_MESSAGE(!ec, ec.message()); BOOST_REQUIRE(c2.in_group(ec)); BOOST_CHECK_MESSAGE(!ec, ec.message()); - g.wait(); + g.wait(ec); BOOST_CHECK(!c1.running()); BOOST_CHECK(!c2.running()); diff --git a/test/v2/ext.cpp b/test/v2/ext.cpp index c82a09ff9..7af93d456 100644 --- a/test/v2/ext.cpp +++ b/test/v2/ext.cpp @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(cmd_exe) BOOST_CHECK_EQUAL(bp2::detail::conv_string(ref.data(), ref.size()), pth); BOOST_REQUIRE_EQUAL(cm.argc(), args.size() + 1); - for (auto i = 0; i < args.size(); i++) + for (auto i = 0u; i < args.size(); i++) { ref = cm.argv()[i + 1];