Beispiel #1
0
    /**
     * Blocks and waits for the process to terminate.
     *
     * Returns an exit code. The process object ceases to be valid after this
     * call.
     *
     * \remark Blocking remarks: This call blocks if the process has not
     *         finalized execution and waits until it terminates.
     *
     * \throw boost::system::system_error If system calls used to wait for the
     *        process fail.
     */
    int wait() const
    {
#if defined(BOOST_POSIX_API)
        pid_t p;
        int status;
        do
        {
            p = waitpid(id_, &status, 0);
        } while (p == -1 && errno == EINTR);
        if (p == -1)
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
        return status;
#elif defined(BOOST_WINDOWS_API)
        HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
            id_);
        if (h == NULL) 
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
        if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
        {
            CloseHandle(h);
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
                "WaitForSingleObject() failed");
        }
        DWORD exit_code;
        if (!GetExitCodeProcess(h, &exit_code))
        {
            CloseHandle(h);
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
                "GetExitCodeProcess() failed");
        }
        if (!CloseHandle(h))
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
        return exit_code;
#endif
    }
Beispiel #2
0
inline DWORD wait_for_exit(const Process &p)
{
    if (::WaitForSingleObject(p.process_handle(), INFINITE) == WAIT_FAILED)
        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed");

    DWORD exit_code;
    if (!::GetExitCodeProcess(p.process_handle(), &exit_code))
        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed");

    return exit_code;
}
Beispiel #3
0
 /**
  * Opens a process and returns a handle.
  *
  * OpenProcess() returns NULL and not INVALID_HANDLE_VALUE on failure.
  * That's why the return value is manually checked in this helper function
  * instead of simply passing it to the constructor of the handle class.
  */
 HANDLE open_process(pid_type id)
 {
     HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, id);
     if (h == NULL)
         BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
     return h;
 }
Beispiel #4
0
inline pipe create_pipe()
{
    HANDLE handles[2];
    if (!::CreatePipe(&handles[0], &handles[1], NULL, 0))
        BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
    return make_pipe(handles[0], handles[1]);
}
Beispiel #5
0
    void async_wait(implementation_type &impl, pid_type pid, Handler handler)
    {
#if defined(BOOST_POSIX_API)
        boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
        if (++pids_ == 1)
        {
            work_.reset(new boost::asio::io_service::work(
                this->get_io_service()));
            work_thread_ = boost::thread(
                &basic_status_service<StatusImplementation>::work_thread,
                this);
        }
        impl->async_wait(pid, this->get_io_service().wrap(handler));
#elif defined(BOOST_WINDOWS_API)
        HANDLE handle = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
            FALSE, pid);
        if (handle == NULL)
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
        boost::unique_lock<boost::mutex> lock(work_thread_mutex_);
        if (!work_)
            work_.reset(new boost::asio::io_service::work(
                this->get_io_service()));
        interrupt_work_thread();
        work_thread_cond_.wait(work_thread_mutex_);
        handles_.push_back(handle);
        impl->async_wait(handle, this->get_io_service().wrap(handler));
        work_thread_cond_.notify_all();
#endif
    }
Beispiel #6
0
    /**
     * Terminates the process execution.
     *
     * Forces the termination of the process execution. Some platforms
     * allow processes to ignore some external termination notifications
     * or to capture them for a proper exit cleanup. You can set the
     * \a force flag to true to force their termination regardless
     * of any exit handler.
     *
     * After this call, accessing this object can be dangerous because the
     * process identifier may have been reused by a different process. It
     * might still be valid, though, if the process has refused to die.
     *
     * \throw boost::system::system_error If system calls used to terminate the
     *        process fail.
     */
    void terminate(bool force = false) const
    {
#if defined(BOOST_POSIX_API)
        if (kill(id_, force ? SIGKILL : SIGTERM) == -1)
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
#elif defined(BOOST_WINDOWS_API)
#if defined(BOOST_MSVC)
        force;
#endif
        HANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, id_);
        if (h == NULL)
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
        if (!TerminateProcess(h, EXIT_FAILURE))
        {
            CloseHandle(h);
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
        }
        if (!CloseHandle(h))
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
#endif
    }
Beispiel #7
0
    bool complete(phandle ph, int exit_code)
    {
        boost::iterator_range<operations_type::iterator> r =
            ops_.equal_range(ph);
        if (r.empty())
            return false;
        for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
            (*it->second)(exit_code);
        ops_.erase(r.begin(), r.end());
#if defined(BOOST_WINDOWS_API)
        if (!CloseHandle(ph))
            BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
#endif
        return true;
    }