I sporadically observe that basic_process::async_wait eventually enters
::waitpid(pid_, &exit_code, 0)
in process_handle_fd.hpp (around line 332). At the time this call is made, the corresponding child process is still running (verified via ps and gdb). Consequently, the parent thread blocks until the child process eventually terminates.
The call stack looks something like:
io_context::poll_one()
-> reactive_wait_op::do_complete()
-> basic_process_handle_fd<...>::async_wait_op_
-> wait4()/waitpid(..., 0)
From reading the implementation of async_wait_op_, my understanding is:
-
The initial operator() calls
waitpid(pid_, &exit_code, WNOHANG)
-
If the process is still running, it registers
descriptor.async_wait(wait_read, ...)
-
The completion handler then calls
waitpid(pid_, &exit_code, 0)
This seems to assume that the descriptor becomes readable only when the child process can be reaped.
However, in the failing cases, the second operator() is entered although the child process is still running. As a consequence, the blocking waitpid(..., 0) blocks the calling thread.
Environment:
- Boost 1.91.0
- Boost.Process V2
- Linux 6.12.0
- BOOST_PROCESS_V2_PIDFD_OPEN == 1
- BOOST_PROCESS_V2_HAS_PROCESS_HANDLE == 1
The application uses Boost.Fiber and calls io_context::poll_one() from a fiber.
Do you have any idea, what the problem could be?
I sporadically observe that basic_process::async_wait eventually enters
in process_handle_fd.hpp (around line 332). At the time this call is made, the corresponding child process is still running (verified via ps and gdb). Consequently, the parent thread blocks until the child process eventually terminates.
The call stack looks something like:
From reading the implementation of async_wait_op_, my understanding is:
The initial operator() calls
If the process is still running, it registers
The completion handler then calls
This seems to assume that the descriptor becomes readable only when the child process can be reaped.
However, in the failing cases, the second operator() is entered although the child process is still running. As a consequence, the blocking waitpid(..., 0) blocks the calling thread.
Environment:
The application uses Boost.Fiber and calls io_context::poll_one() from a fiber.
Do you have any idea, what the problem could be?