exit_code.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //
  2. // process/exit_code.hpp
  3. // ~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2022 Klemens D. Morgenstern (klemens dot morgenstern at gmx dot net)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_PROCESS_V2_EXIT_CODE_HPP
  11. #define BOOST_PROCESS_V2_EXIT_CODE_HPP
  12. #include <boost/process/v2/detail/config.hpp>
  13. #include <boost/process/v2/error.hpp>
  14. #if defined(BOOST_PROCESS_V2_STANDALONE)
  15. #include <asio/associator.hpp>
  16. #include <asio/async_result.hpp>
  17. #else
  18. #include <boost/asio/associator.hpp>
  19. #include <boost/asio/async_result.hpp>
  20. #endif
  21. #if defined(BOOST_PROCESS_V2_POSIX)
  22. #include <sys/wait.h>
  23. #endif
  24. BOOST_PROCESS_V2_BEGIN_NAMESPACE
  25. #if defined(GENERATING_DOCUMENTATION)
  26. /// The native exit-code type, usually an integral value
  27. /** The OS may have a value different from `int` to represent
  28. * the exit codes of subprocesses. It might also
  29. * contain additional information.
  30. */
  31. typedef implementation_defined native_exit_code_type;
  32. /// Check if the native exit code indicates the process is still running
  33. bool process_is_running(native_exit_code_type code);
  34. /// Obtain the portable part of the exit code, i.e. what the subprocess has returned from main.
  35. int evaluate_exit_code(native_exit_code_type code);
  36. #else
  37. #if defined(BOOST_PROCESS_V2_WINDOWS)
  38. typedef unsigned long native_exit_code_type;
  39. namespace detail
  40. {
  41. constexpr native_exit_code_type still_active = 259u;
  42. }
  43. inline bool process_is_running(native_exit_code_type code)
  44. {
  45. return code == detail::still_active;
  46. }
  47. inline int evaluate_exit_code(native_exit_code_type code)
  48. {
  49. return static_cast<int>(code);
  50. }
  51. #else
  52. typedef int native_exit_code_type;
  53. namespace detail
  54. {
  55. constexpr native_exit_code_type still_active = 0x7f;
  56. }
  57. inline bool process_is_running(int code)
  58. {
  59. return !WIFEXITED(code) && !WIFSIGNALED(code);
  60. }
  61. inline int evaluate_exit_code(int code)
  62. {
  63. if (WIFEXITED(code))
  64. return WEXITSTATUS(code);
  65. else if (WIFSIGNALED(code))
  66. return WTERMSIG(code);
  67. else
  68. return code;
  69. }
  70. #endif
  71. #endif
  72. /// @{
  73. /** Helper to subsume an exit-code into an error_code if there's no actual error isn't set.
  74. * @code {.cpp}
  75. * process proc{ctx, "exit", {"1"}};
  76. *
  77. * proc.async_wait(
  78. * asio::deferred(
  79. * [&proc](error_code ec, int)
  80. * {
  81. * return asio::deferred.values(
  82. * check_exit_code(ec, proc.native_exit_code())
  83. * );
  84. *
  85. * [](error_code ec)
  86. * {
  87. * assert(ec.value() == 10);
  88. * assert(ec.category() == error::get_exit_code_category());
  89. * }));
  90. *
  91. * @endcode
  92. */
  93. inline error_code check_exit_code(
  94. error_code &ec, native_exit_code_type native_code,
  95. const error_category & category = error::get_exit_code_category())
  96. {
  97. if (!ec)
  98. BOOST_PROCESS_V2_ASSIGN_EC(ec, native_code, category);
  99. return ec;
  100. }
  101. /// @}
  102. BOOST_PROCESS_V2_END_NAMESPACE
  103. #endif //BOOST_PROCESS_V2_EXIT_CODE_HPP