c++boostboost-asioc++-coroutineboost-process

Getting co_await with boost::process::async_system working


Like the title says, I want to co_await for a process spawned with boost::process::async_system.

So I'm doing something like this:

Example on Coliru

  namespace bp = boost::process;
  bp::async_pipe ap(io_);

  // Create the child process object with our parameters and a redirected stdout
  co_await bp::async_system(io_,
                            boost::asio::use_awaitable,
                            bp::search_path(command),
                            bp::start_dir(cwd),
                            bp::args(args),
                            bp::std_out > ap);

But I'm getting a very unhelpful error-message.

My assumption now is, that async_system is not compatible with co_await. Is there another (maybe generic) way to integrate 3rd party async mechanisms in boost::asio::awaitable?

(I feel a bit lost in this whole boost::asio / c++ coro topic. Google is not very helpful and the boost doc a bit too minimalistic for me.)


Solution

  • I'd mold the code a bit for style: http://coliru.stacked-crooked.com/a/33667a7d106de0e7

    The Real Problem

    Now with the above, there's is still an error inside my_coro when you try to uncomment the async_system call.

    Instead of reading the message, I looked at the code, figured that it should have worked, and looked at the implementation:

    template<typename ExitHandler, typename ...Args>
    inline BOOST_ASIO_INITFN_RESULT_TYPE(ExitHandler, void (boost::system::error_code, int))
        async_system(boost::asio::io_context & ios, ExitHandler && exit_handler, Args && ...args)
    {
        detail::async_system_handler<ExitHandler> async_h{ios, std::forward<ExitHandler>(exit_handler)};
    
        typedef typename ::boost::process::detail::has_error_handler<boost::fusion::tuple<Args...>>::type
                has_err_handling;
    
        static_assert(!has_err_handling::value, "async_system cannot have custom error handling");
    
    
        child(ios, std::forward<Args>(args)..., async_h ).detach();
    
        return async_h.get_result();
    }
    

    After looking at the implementation, I figured that

    /usr/local/include/boost/asio/async_result.hpp:651:9: error: no type named 'completion_handler_type' in 'class boost::asio::async_result<boost::asio::use_awaitable_t<>, void(boost::system::error_code, int)>'
    

    indicates that Boost Process has not been updated to support newer async_result protocol, which instead of completion_handler_type appears to use the initiate member function. This gives the async_result implementation more options, which are probably required for use_awaitable_t tokens.

    I'd raise an issue at the library.

    Note that current develop branch has code underway that does seem to correctly support use_awaitable (e.v. boost/process/v2/popen.hpp)