Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:09

0001 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
0002 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
0003 // Copyright (c) 2009 Boris Schaeling
0004 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
0005 // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
0006 // Copyright (c) 2016 Klemens D. Morgenstern
0007 //
0008 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0009 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0010 
0011 /**
0012  * \file boost/process/child.hpp
0013  *
0014  * Defines a child process class.
0015  */
0016 
0017 #ifndef BOOST_PROCESS_CHILD_DECL_HPP
0018 #define BOOST_PROCESS_CHILD_DECL_HPP
0019 
0020 #include <boost/process/detail/config.hpp>
0021 #include <chrono>
0022 #include <memory>
0023 
0024 #include <boost/none.hpp>
0025 #include <atomic>
0026 
0027 #if defined(BOOST_POSIX_API)
0028 #include <boost/process/detail/posix/child_handle.hpp>
0029 #include <boost/process/detail/posix/terminate.hpp>
0030 #include <boost/process/detail/posix/wait_for_exit.hpp>
0031 #include <boost/process/detail/posix/is_running.hpp>
0032 #elif defined(BOOST_WINDOWS_API)
0033 #include <boost/process/detail/windows/child_handle.hpp>
0034 #include <boost/process/detail/windows/terminate.hpp>
0035 #include <boost/process/detail/windows/wait_for_exit.hpp>
0036 #include <boost/process/detail/windows/is_running.hpp>
0037 
0038 #endif
0039 namespace boost {
0040 
0041 namespace process {
0042 
0043 using ::boost::process::detail::api::pid_t;
0044 
0045 class child
0046 {
0047     ::boost::process::detail::api::child_handle _child_handle;
0048     std::shared_ptr<std::atomic<int>> _exit_status = std::make_shared<std::atomic<int>>(::boost::process::detail::api::still_active);
0049     bool _attached = true;
0050     bool _terminated = false;
0051 
0052     bool _exited()
0053     {
0054         return _terminated || !::boost::process::detail::api::is_running(_exit_status->load());
0055     };
0056 public:
0057     typedef ::boost::process::detail::api::child_handle child_handle;
0058     typedef child_handle::process_handle_t native_handle_t;
0059     explicit child(child_handle &&ch, std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
0060     explicit child(child_handle &&ch, const std::shared_ptr<std::atomic<int>> &ptr) : _child_handle(std::move(ch)), _exit_status(ptr) {}
0061     explicit child(child_handle &&ch) : _child_handle(std::move(ch)) {}
0062 
0063     explicit child(pid_t pid) : _child_handle(pid), _attached(false) {};
0064     child(const child&) = delete;
0065     child(child && lhs) noexcept
0066         : _child_handle(std::move(lhs._child_handle)),
0067           _exit_status(std::move(lhs._exit_status)),
0068           _attached (lhs._attached),
0069           _terminated (lhs._terminated)
0070     {
0071         lhs._attached = false;
0072     }
0073 
0074     template<typename ...Args>
0075     explicit child(Args&&...args);
0076     child() { } // Must be kept non defaulted for MSVC 14.1 & 14.2 #113
0077     child& operator=(const child&) = delete;
0078     child& operator=(child && lhs)
0079     {
0080         _child_handle= std::move(lhs._child_handle);
0081         _exit_status = std::move(lhs._exit_status);
0082         _attached    = lhs._attached;
0083         _terminated  = lhs._terminated;
0084         lhs._attached = false;
0085         return *this;
0086     };
0087 
0088     void detach() {_attached = false; }
0089     void join() {wait();}
0090     bool joinable() { return _attached;}
0091 
0092     ~child()
0093     {
0094         std::error_code ec;
0095         if (_attached && !_exited() && running(ec))
0096             terminate(ec);
0097     }
0098     native_handle_t native_handle() const { return _child_handle.process_handle(); }
0099 
0100 
0101     int exit_code() const {return ::boost::process::detail::api::eval_exit_status(_exit_status->load());}
0102     pid_t id()      const {return _child_handle.id(); }
0103 
0104     int native_exit_code() const {return _exit_status->load();}
0105 
0106     bool running()
0107     {
0108         std::error_code ec;
0109         bool b = running(ec);
0110         boost::process::detail::throw_error(ec, "running error");
0111         return b;
0112     }
0113 
0114     void terminate()
0115     {
0116         std::error_code ec;
0117         terminate(ec);
0118         boost::process::detail::throw_error(ec, "terminate error");
0119     }
0120 
0121     void wait()
0122     {
0123         std::error_code ec;
0124         wait(ec);
0125         boost::process::detail::throw_error(ec, "wait error");
0126     }
0127 
0128 #if !defined(BOOST_PROCESS_NO_DEPRECATED)
0129 
0130     template< class Rep, class Period >
0131     BOOST_DEPRECATED("wait_for is unreliable")
0132     bool wait_for (const std::chrono::duration<Rep, Period>& rel_time)
0133     {
0134         std::error_code ec;
0135         bool b = wait_for(rel_time, ec);
0136         boost::process::detail::throw_error(ec, "wait_for error");
0137         return b;
0138     }
0139 
0140     template< class Clock, class Duration >
0141     BOOST_DEPRECATED("wait_until is unreliable")
0142     bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time )
0143     {
0144         std::error_code ec;
0145         bool b = wait_until(timeout_time, ec);
0146         boost::process::detail::throw_error(ec, "wait_until error");
0147         return b;
0148     }
0149 #endif
0150 
0151     bool running(std::error_code & ec) noexcept
0152     {
0153         ec.clear();
0154         if (valid() && !_exited() && !ec)
0155         {
0156             int exit_code = 0;
0157             auto res = boost::process::detail::api::is_running(_child_handle, exit_code, ec);
0158             if (!ec && !res && !_exited())
0159                 _exit_status->store(exit_code);
0160 
0161             return res;
0162         }
0163         return false;
0164     }
0165 
0166     void terminate(std::error_code & ec) noexcept
0167     {
0168         if (valid() && running(ec) && !ec)
0169             boost::process::detail::api::terminate(_child_handle, ec);
0170 
0171         if (!ec)
0172             _terminated = true;
0173     }
0174 
0175     void wait(std::error_code & ec) noexcept
0176     {
0177         if (!_exited() && valid())
0178         {
0179             int exit_code = 0;
0180             boost::process::detail::api::wait(_child_handle, exit_code, ec);
0181             if (!ec)
0182                 _exit_status->store(exit_code);
0183         }
0184     }
0185 
0186 #if !defined(BOOST_PROCESS_NO_DEPRECATED)
0187     template< class Rep, class Period >
0188     BOOST_DEPRECATED("wait_for is unreliable")
0189     bool wait_for (const std::chrono::duration<Rep, Period>& rel_time, std::error_code & ec) noexcept
0190     {
0191         return wait_until(std::chrono::steady_clock::now() + rel_time, ec);
0192     }
0193 
0194     template< class Clock, class Duration >
0195     BOOST_DEPRECATED("wait_until is unreliable")
0196     bool wait_until(const std::chrono::time_point<Clock, Duration>& timeout_time, std::error_code & ec) noexcept
0197     {
0198         if (!_exited())
0199         {
0200             int exit_code = 0;
0201             auto b = boost::process::detail::api::wait_until(_child_handle, exit_code, timeout_time, ec);
0202             if (!b || ec)
0203                 return false;
0204             _exit_status->store(exit_code);
0205         }
0206         return true;
0207     }
0208 #endif
0209 
0210     bool valid() const
0211     {
0212         return _child_handle.valid();
0213     }
0214     operator bool() const {return valid();}
0215 
0216     bool in_group() const
0217     {
0218         return _child_handle.in_group();
0219     }
0220     bool in_group(std::error_code &ec) const noexcept
0221     {
0222         return _child_handle.in_group(ec);
0223     }
0224 };
0225 
0226 
0227 
0228 }}
0229 #endif
0230