io_context_ref.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright (c) 2016 Klemens D. Morgenstern
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
  6. #define BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_
  7. #include <boost/process/detail/posix/handler.hpp>
  8. #include <boost/process/detail/posix/async_handler.hpp>
  9. #include <boost/asio/io_context.hpp>
  10. #include <boost/fusion/algorithm/iteration/for_each.hpp>
  11. #include <boost/fusion/algorithm/transformation/filter_if.hpp>
  12. #include <boost/fusion/algorithm/transformation/transform.hpp>
  13. #include <boost/fusion/view/transform_view.hpp>
  14. #include <boost/fusion/container/vector/convert.hpp>
  15. #include <boost/process/detail/posix/sigchld_service.hpp>
  16. #include <boost/process/detail/posix/is_running.hpp>
  17. #include <functional>
  18. #include <type_traits>
  19. #include <memory>
  20. #include <vector>
  21. #include <sys/wait.h>
  22. namespace boost { namespace process { namespace detail { namespace posix {
  23. template<typename Executor>
  24. struct on_exit_handler_transformer
  25. {
  26. Executor & exec;
  27. on_exit_handler_transformer(Executor & exec) : exec(exec) {}
  28. template<typename Sig>
  29. struct result;
  30. template<typename T>
  31. struct result<on_exit_handler_transformer<Executor>(T&)>
  32. {
  33. typedef typename T::on_exit_handler_t type;
  34. };
  35. template<typename T>
  36. auto operator()(T& t) const -> typename T::on_exit_handler_t
  37. {
  38. return t.on_exit_handler(exec);
  39. }
  40. };
  41. template<typename Executor>
  42. struct async_handler_collector
  43. {
  44. Executor & exec;
  45. std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
  46. async_handler_collector(Executor & exec,
  47. std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
  48. : exec(exec), handlers(handlers) {}
  49. template<typename T>
  50. void operator()(T & t) const
  51. {
  52. handlers.push_back(t.on_exit_handler(exec));
  53. }
  54. };
  55. //Also set's up waiting for the exit, so it can close async stuff.
  56. struct io_context_ref : handler_base_ext
  57. {
  58. io_context_ref(boost::asio::io_context & ios) : ios(ios)
  59. {
  60. }
  61. boost::asio::io_context &get() {return ios;};
  62. template <class Executor>
  63. void on_success(Executor& exec)
  64. {
  65. ios.notify_fork(boost::asio::io_context::fork_parent);
  66. //must be on the heap so I can move it into the lambda.
  67. auto asyncs = boost::fusion::filter_if<
  68. is_async_handler<
  69. typename std::remove_reference< boost::mpl::_ > ::type
  70. >>(exec.seq);
  71. //ok, check if there are actually any.
  72. if (boost::fusion::empty(asyncs))
  73. return;
  74. std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
  75. funcs.reserve(boost::fusion::size(asyncs));
  76. boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
  77. auto & es = exec.exit_status;
  78. auto wh = [funcs, es](int val, const std::error_code & ec)
  79. {
  80. es->store(val);
  81. for (auto & func : funcs)
  82. func(::boost::process::detail::posix::eval_exit_status(val), ec);
  83. };
  84. sigchld_service.async_wait(exec.pid, std::move(wh));
  85. }
  86. template<typename Executor>
  87. void on_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_prepare);*/}
  88. template<typename Executor>
  89. void on_exec_setup (Executor &) const {/*ios.notify_fork(boost::asio::io_context::fork_child);*/}
  90. template <class Executor>
  91. void on_error(Executor&, const std::error_code &) const {/*ios.notify_fork(boost::asio::io_context::fork_parent);*/}
  92. private:
  93. boost::asio::io_context &ios;
  94. boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios);
  95. };
  96. }}}}
  97. #endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */