2
0
mirror of https://github.com/boostorg/process.git synced 2026-01-19 04:22:15 +00:00

posix: Add test for pipe fd leak if redirecting both stdout and stderr

Signed-off-by: Daniel Klauer <daniel.klauer@gin.de>
This commit is contained in:
Daniel Klauer
2024-04-17 16:42:59 +02:00
committed by Klemens Morgenstern
parent e8b5bf17f0
commit e455a12e2c

View File

@@ -170,4 +170,47 @@ BOOST_AUTO_TEST_CASE(leak_test, *boost::unit_test::timeout(5))
BOOST_CHECK_EQUAL(fd_list.size(), fd_list_new.size());
}
}
BOOST_AUTO_TEST_CASE(pipe_fd_is_not_leaked, *boost::unit_test::timeout(5))
{
const std::string partner = boost::unit_test::framework::master_test_suite().argv[1];
#define test(parent_closes_source, fd_to_check, expected_exitcode, call_args...) \
do { \
boost::asio::io_context ioctx; \
bp::async_pipe pipe(ioctx); \
BOOST_CHECK_NE(pipe.native_source(), -1); \
BOOST_CHECK_NE(pipe.native_sink(), -1); \
BOOST_CHECK_EQUAL(bp::system(partner, "--has-handle", std::to_string(fd_to_check), call_args), expected_exitcode); \
if (parent_closes_source) { \
BOOST_CHECK_EQUAL(pipe.native_source(), -1); \
BOOST_CHECK_NE(pipe.native_sink(), -1); \
} else { \
BOOST_CHECK_NE(pipe.native_source(), -1); \
BOOST_CHECK_EQUAL(pipe.native_sink(), -1); \
} \
} while (0)
// Both parent and child processes must close the end of the pipe which they don't use,
// and pipe_in/pipe_out must close the original source/sink fd after redirecting in the child process,
// so that they don't keep the pipe open unnecessarily.
test(true, STDIN_FILENO , EXIT_SUCCESS, bp::std_in < pipe);
test(true, pipe.native_source(), EXIT_FAILURE, bp::std_in < pipe);
test(true, pipe.native_sink() , EXIT_FAILURE, bp::std_in < pipe);
test(false, STDOUT_FILENO , EXIT_SUCCESS, bp::std_out > pipe);
test(false, pipe.native_source(), EXIT_FAILURE, bp::std_out > pipe);
test(false, pipe.native_sink() , EXIT_FAILURE, bp::std_out > pipe);
test(false, STDERR_FILENO , EXIT_SUCCESS, bp::std_err > pipe);
test(false, pipe.native_source(), EXIT_FAILURE, bp::std_err > pipe);
test(false, pipe.native_sink() , EXIT_FAILURE, bp::std_err > pipe);
test(false, STDOUT_FILENO , EXIT_SUCCESS, (bp::std_out & bp::std_err) > pipe);
test(false, STDERR_FILENO , EXIT_SUCCESS, (bp::std_out & bp::std_err) > pipe);
test(false, pipe.native_source(), EXIT_FAILURE, (bp::std_out & bp::std_err) > pipe);
test(false, pipe.native_sink() , EXIT_FAILURE, (bp::std_out & bp::std_err) > pipe);
#undef test
}