Beispiel #1
0
/// Waits for completion of any forked process.
///
/// \return A pointer to an object describing the waited-for subprocess.
executor::exit_handle
executor::executor_handle::wait_any(void)
{
    signals::check_interrupt();
    const process::status status = process::wait_any();
    return _pimpl->post_wait(status.dead_pid(), status);
}
Beispiel #2
0
/// Blocks to wait for completion of any subprocess.
///
/// \return The termination status of the child process that terminated.
///
/// \throw process::system_error If the call to wait(2) fails.
process::status
process::wait_any(void)
{
    const process::status status = safe_wait();
    {
        signals::interrupts_inhibiter inhibiter;
        signals::remove_pid_to_kill(status.dead_pid());
    }
    return status;
}
Beispiel #3
0
    /// Common code to run after any of the wait calls.
    ///
    /// \param handle The exec_handle of the terminated subprocess.
    /// \param status The exit status of the terminated subprocess.
    ///
    /// \return A pointer to an object describing the waited-for subprocess.
    executor::exit_handle
    post_wait(const executor::exec_handle handle, const process::status& status)
    {
        PRE(handle == status.dead_pid());
        LI(F("Waited for subprocess with exec_handle %s") % handle);

        process::terminate_group(status.dead_pid());

        const exec_data_map::iterator iter = all_exec_data.find(handle);
        exec_data_ptr& data = (*iter).second;
        data->timer.unprogram();

        // It is tempting to assert here (and old code did) that, if the timer
        // has fired, the process has been forcibly killed by us.  This is not
        // always the case though: for short-lived processes and with very short
        // timeouts (think 1ms), it is possible for scheduling decisions to
        // allow the subprocess to finish while at the same time cause the timer
        // to fire.  So we do not assert this any longer and just rely on the
        // timer expiration to check if the process timed out or not.  If the
        // process did finish but the timer expired... oh well, we do not detect
        // this correctly but we don't care because this should not really
        // happen.

        if (!fs::exists(data->stdout_file)) {
            std::ofstream new_stdout(data->stdout_file.c_str());
        }
        if (!fs::exists(data->stderr_file)) {
            std::ofstream new_stderr(data->stderr_file.c_str());
        }

        return exit_handle(std::shared_ptr< exit_handle::impl >(
            new exit_handle::impl(
                handle,
                data->timer.fired() ? none : utils::make_optional(status),
                data->unprivileged_user,
                data->start_time, datetime::timestamp::now(),
                data->control_directory,
                data->stdout_file,
                data->stderr_file,
                data->state_owners,
                all_exec_data)));
    }