Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boost::process:: child::wait() on Linux ignores a zombie process #217

Open
theroyn opened this issue Aug 19, 2021 · 2 comments
Open

boost::process:: child::wait() on Linux ignores a zombie process #217

theroyn opened this issue Aug 19, 2021 · 2 comments

Comments

@theroyn
Copy link

theroyn commented Aug 19, 2021

Reproducible in the following example:

#include <boost/process.hpp>

int main()
{
        namespace bp = boost::process;

        std::string appCommand = "sleep 50";
        bp::child childProcess(appCommand);

        int pid = childProcess.id();

        printf("childProcess.running()=%d\n", childProcess.running());

        childProcess.terminate();
        childProcess.wait();

        printf("childProcess.running()=%d\n", childProcess.running());

        // kill 0 returns 0 if process is running
        bool isRunning = (::kill(pid, 0) == 0);

        printf("isRunning=%d\n", isRunning);
}

output on my machine is:

childProcess.running()=1
childProcess.running()=0
(kill 0 23764): isRunning=1

The program will print isRunning=1 at its end, meaning that the process is still running. Pausing at that point with debugger and checking ps -ax will also show that the process is a zombie.

After some investigation, faulty code seem to be in include/boost/process/detail/child_decl.hpp:

    bool _exited()
    {
        return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());
    };

    void terminate(std::error_code & ec) noexcept
    {
        if (valid() && running(ec) && !ec)
            boost::process::detail::api::terminate(_child_handle, ec);

        if (!ec)
            _terminated = true;
    }

    void wait(std::error_code & ec) noexcept
    {
        if (!_exited() && valid())
        {
            int exit_code = 0;
            boost::process::detail::api::wait(_child_handle, exit_code, ec);
            if (!ec)
                _exit_status->store(exit_code);
        }
    }

terminate() marks _terminated = true, and wait() never calls its main logic because _exited() evaluates true.

A possible solution would be to perform a blocking wait at the end of boost::process::detail::api::terminate(), because ATM it waits with WNOHANG.

@theroyn theroyn changed the title boost::process:child::wait() on Linux ignores a zombie process boost::process::child::wait() on Linux ignores a zombie process Aug 19, 2021
@theroyn theroyn changed the title boost::process::child::wait() on Linux ignores a zombie process boost::process:: child::wait() on Linux ignores a zombie process Aug 19, 2021
@SilverPlate3
Copy link
Contributor

@klemens-morgenstern
Do you want me to create a pull request and fix this issue?

@klemens-morgenstern
Copy link
Collaborator

I think I fixed this, maybe add a test for it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants