| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- //
- // process/exit_code.hpp
- // ~~~~~~~~~~~~~~
- //
- // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef BOOST_PROCESS_V2_EXIT_CODE_HPP
- #define BOOST_PROCESS_V2_EXIT_CODE_HPP
- #include <boost/process/v2/detail/config.hpp>
- #include <boost/process/v2/error.hpp>
- #if defined(BOOST_PROCESS_V2_STANDALONE)
- #include <asio/associator.hpp>
- #include <asio/async_result.hpp>
- #else
- #include <boost/asio/associator.hpp>
- #include <boost/asio/async_result.hpp>
- #endif
- #if defined(BOOST_PROCESS_V2_POSIX)
- #include <sys/wait.h>
- #endif
- BOOST_PROCESS_V2_BEGIN_NAMESPACE
- #if defined(GENERATING_DOCUMENTATION)
- /// The native exit-code type, usually an integral value
- /** The OS may have a value different from `int` to represent
- * the exit codes of subprocesses. It might also
- * contain additional information.
- */
- typedef implementation_defined native_exit_code_type;
- /// Check if the native exit code indicates the process is still running
- bool process_is_running(native_exit_code_type code);
- /// Obtain the portable part of the exit code, i.e. what the subprocess has returned from main.
- int evaluate_exit_code(native_exit_code_type code);
- #else
- #if defined(BOOST_PROCESS_V2_WINDOWS)
- typedef unsigned long native_exit_code_type;
- namespace detail
- {
- constexpr native_exit_code_type still_active = 259u;
- }
- inline bool process_is_running(native_exit_code_type code)
- {
- return code == detail::still_active;
- }
- inline int evaluate_exit_code(native_exit_code_type code)
- {
- return static_cast<int>(code);
- }
- #else
- typedef int native_exit_code_type;
- namespace detail
- {
- constexpr native_exit_code_type still_active = 0x7f;
- }
- inline bool process_is_running(int code)
- {
- return !WIFEXITED(code) && !WIFSIGNALED(code);
- }
- inline int evaluate_exit_code(int code)
- {
- if (WIFEXITED(code))
- return WEXITSTATUS(code);
- else if (WIFSIGNALED(code))
- return WTERMSIG(code);
- else
- return code;
- }
- #endif
- #endif
- /** Convert the exit-code in a completion into an error if the actual error isn't set.
- * @code {.cpp}
- * process proc{ctx, "exit", {"1"}};
- *
- * proc.async_wait(code_as_error(
- * [](error_code ec)
- * {
- * assert(ec.value() == 10);
- * assert(ec.category() == error::get_exit_code_category());
- * }));
- *
- * @endcode
- */
- template<typename CompletionToken>
- struct code_as_error_t
- {
- CompletionToken token_;
- const error_category & category;
- template<typename Token_>
- code_as_error_t(Token_ && token, const error_category & category)
- : token_(std::forward<Token_>(token)), category(category)
- {
- }
- };
- /// Deduction function for code_as_error_t.
- template<typename CompletionToken>
- code_as_error_t<CompletionToken> code_as_error(
- CompletionToken && token,
- const error_category & category = error::get_exit_code_category())
- {
- return code_as_error_t<typename std::decay<CompletionToken>::type>(
- std::forward<CompletionToken>(token), category);
- };
- namespace detail
- {
- template<typename Handler>
- struct code_as_error_handler
- {
- typedef void result_type;
- template<typename H>
- code_as_error_handler(H && h, const error_category & category)
- : handler_(std::forward<H>(h)), category(category)
- {
- }
- void operator()(error_code ec, native_exit_code_type code)
- {
- if (!ec)
- BOOST_PROCESS_V2_ASSIGN_EC(ec, code, category)
- std::move(handler_)(ec);
- }
- Handler handler_;
- const error_category & category;
- };
- }
- BOOST_PROCESS_V2_END_NAMESPACE
- #if !defined(BOOST_PROCESS_V2_STANDALONE)
- namespace boost
- {
- #endif
- namespace asio
- {
- template <typename CompletionToken>
- struct async_result<
- BOOST_PROCESS_V2_NAMESPACE::code_as_error_t<CompletionToken>,
- void(BOOST_PROCESS_V2_NAMESPACE::error_code,
- BOOST_PROCESS_V2_NAMESPACE::native_exit_code_type)>
- {
- using signature = void(BOOST_PROCESS_V2_NAMESPACE::error_code);
- using return_type = typename async_result<CompletionToken, void(BOOST_PROCESS_V2_NAMESPACE::error_code)>::return_type;
-
- template <typename Initiation>
- struct init_wrapper
- {
- init_wrapper(Initiation init)
- : initiation_(std::move(init))
- {
- }
- template <typename Handler, typename... Args>
- void operator()(
- Handler && handler,
- const BOOST_PROCESS_V2_NAMESPACE::error_category & cat,
- Args && ... args)
- {
- std::move(initiation_)(
- BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<typename decay<Handler>::type>(
- std::forward<Handler>(handler), cat),
- std::forward<Args>(args)...);
- }
- Initiation initiation_;
- };
- template <typename Initiation, typename RawCompletionToken, typename... Args>
- static BOOST_PROCESS_V2_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,
- (async_initiate<CompletionToken, signature>(
- declval<init_wrapper<typename decay<Initiation>::type> >(),
- declval<CompletionToken&>(),
- declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
- initiate(
- Initiation && initiation,
- RawCompletionToken && token,
- Args &&... args)
- {
- return async_initiate<CompletionToken, signature>(
- init_wrapper<typename decay<Initiation>::type>(
- std::forward<Initiation>(initiation)),
- token.token_,
- token.category,
- std::forward<Args>(args)...);
- }
- };
- template<template <typename, typename> class Associator, typename Handler, typename DefaultCandidate>
- struct associator<Associator,
- BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<Handler>, DefaultCandidate>
- : Associator<Handler, DefaultCandidate>
- {
- static typename Associator<Handler, DefaultCandidate>::type get(
- const BOOST_PROCESS_V2_NAMESPACE::detail::code_as_error_handler<Handler> & h,
- const DefaultCandidate& c = DefaultCandidate()) noexcept
- {
- return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
- }
- };
- }
- #if !defined(BOOST_PROCESS_V2_STANDALONE)
- } // boost
- #endif
- #endif //BOOST_PROCESS_V2_EXIT_CODE_HPP
|