Skip to content

Commit

Permalink
zombie process fixes
Browse files Browse the repository at this point in the history
closes #445, #447
  • Loading branch information
klemens-morgenstern committed Jan 13, 2025
1 parent 1b5272a commit a2d2753
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 39 deletions.
44 changes: 6 additions & 38 deletions include/boost/process/v2/posix/default_launcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#endif

#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>


Expand Down Expand Up @@ -96,7 +98,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_error(launcher, executable, cmd_line, ec))
{
init.on_error(launcher, executable, cmd_line, ec);
}
Expand Down Expand Up @@ -160,7 +162,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_fork_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_fork_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_fork_error(launcher, executable, cmd_line, ec))
{
init.on_fork_error(launcher, executable, cmd_line, ec);
}
Expand All @@ -182,41 +184,6 @@ inline void on_fork_error(Launcher & launcher, const filesystem::path &executabl
on_fork_error(launcher, executable, cmd_line, ec, inits...);
}



template<typename Launcher, typename Init>
inline void invoke_on_fork_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/),
Init && /*init*/, base && )
{

}

template<typename Launcher, typename Init>
inline auto invoke_on_fork_success(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
Init && init, derived && )
-> decltype(init.on_fork_success(launcher, executable, cmd_line))
{
init.on_fork_success(launcher, executable, cmd_line);
}

template<typename Launcher>
inline void on_fork_success(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/))
{
}

template<typename Launcher, typename Init1, typename ... Inits>
inline void on_fork_success(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
Init1 && init1, Inits && ... inits)
{
invoke_on_fork_success(launcher, executable, cmd_line, init1, derived{});
on_fork_success(launcher, executable, cmd_line, inits...);
}


template<typename Launcher, typename Init>
inline error_code invoke_on_exec_setup(Launcher & /*launcher*/, const filesystem::path &/*executable*/,
const char * const * (&/*cmd_line*/),
Expand Down Expand Up @@ -266,7 +233,7 @@ template<typename Launcher, typename Init>
inline auto invoke_on_exec_error(Launcher & launcher, const filesystem::path &executable,
const char * const * (&cmd_line),
const error_code & ec, Init && init, derived && )
-> decltype(init.on_exec_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_exec_error(launcher, executable, cmd_line, ec))
{
init.on_exec_error(launcher, executable, cmd_line, ec);
}
Expand Down Expand Up @@ -440,6 +407,7 @@ struct default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ struct fork_and_forget_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}
Expand Down
1 change: 1 addition & 0 deletions include/boost/process/v2/posix/pdfork_launcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct pdfork_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}
}
Expand Down
1 change: 1 addition & 0 deletions include/boost/process/v2/posix/vfork_launcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ struct vfork_launcher : default_launcher
if (ec)
{
detail::on_error(*this, executable, argv, ec, inits...);
do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
return basic_process<Executor>{exec};
}

Expand Down
2 changes: 1 addition & 1 deletion include/boost/process/v2/windows/default_launcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ inline void invoke_on_error(Launcher & /*launcher*/, const filesystem::path &/*e
template<typename Launcher, typename Init>
inline auto invoke_on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
const error_code & ec, Init && init, derived && )
-> decltype(init.on_error(launcher, ec, executable, cmd_line, ec))
-> decltype(init.on_error(launcher, executable, cmd_line, ec))
{
init.on_error(launcher, executable, cmd_line, ec);
}
Expand Down
36 changes: 36 additions & 0 deletions test/v2/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,42 @@ BOOST_AUTO_TEST_CASE(async_cancel_wait)
ctx.run();
}

#if defined(BOOST_POSIX_API)

struct capture_pid
{
pid_t &pid;
template<typename Launcher>
void on_error(Launcher &launcher, const bpv::filesystem::path& executable,
const char * const * (&/*cmd_line*/), const bpv::error_code & ec)
{
BOOST_REQUIRE(!bpv::filesystem::exists(executable));
this->pid = launcher.pid;
}
};

BOOST_AUTO_TEST_CASE(no_zombie)
{
asio::io_context ctx;
using boost::unit_test::framework::master_test_suite;
const auto pth = bpv::filesystem::absolute(master_test_suite().argv[1]);

pid_t res{-1};


boost::system::error_code ec;
bpv::default_process_launcher()(ctx, ec, "/send/more/cops", std::vector<std::string>{}, capture_pid{res});
BOOST_CHECK(ec == boost::system::errc::no_such_file_or_directory);

BOOST_REQUIRE(res != -1);
BOOST_CHECK(res != 0);
auto r = waitpid(res, nullptr, 0);
BOOST_CHECK(r < 0);
BOOST_CHECK_EQUAL(errno, ECHILD);
}

#endif


BOOST_AUTO_TEST_SUITE_END();

0 comments on commit a2d2753

Please sign in to comment.