2017-12-05 50 views
1

私はboost::process::childboost::process::async_pipeを使用してアプリケーションを起動し、このときにいつでもアプリが出力するすべてのものを非同期的に(boost::asioを介して)読み込みます。ブーストプロセスの実行()とスレッドセーフティーのexit_code()

child::running()メソッドを使用してアプリケーションが生存しているかどうかもチェックしたいと思います。実行していない場合は、child::exit_codeを使用して終了コードを読みたいと思います。

非常に便利ですESPECIALLYこれはアプリケーションが予期せずクラッシュしたり終了したりするのを通知する方法です(私はより良い方法を見つけることができませんでした)。アプリがコールバックを終了するときにboost::system::error_codeが設定されて呼び出されます。

async_pipe::async_read_someというコールバックでこれらの2つの方法を使用できるかどうか知りませんか?

一般に、より簡単な質問は、child::running()child::exit_code()がスレッドセーフ(WindowsとLinuxの両方)の場合です。

namespace bp = boost::process; 

char my_buffer[1024]; 

boost::asio::io_service io; 
bp::async_pipe in_pipe(io); 

void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred); 

void schedule_read() { 
    in_pipe.async_read_some(
     boost::asio::buffer(my_buffer), 
     boost::bind(&handle_pipe_read, 
        boost::asio::placeholders::error, 
        boost::asio::placeholders::bytes_transferred)); 
} 

void handle_pipe_read(
    const boost::system::error_code &ec, 
    std::size_t bytes_transferred 
    ) 
{ 
    // Q: Is this call possible? 'handle_pipe_read' can run in any thread 
    if(c->running()) 
     std::cout << "I am alive" << std::endl; 
    else 
     std::cout << "EXIT CODE:" << c->exit_code() << std::endl; 

    if(ec) return; //app probably exit 

    // Do something with buffer and re-schedule 

    schedule_read(); 
} 

int main() { 
    bp::child c("my_program_url", bp::std_out > in_pipe); 
    any_c = &c; 

    schedule_read(); 
    io.run();  
} 

答えて

1

あなただけのメインスレッド上でio_service::run()を実行しているので、すべての完了ハンドラもあっ実行します。スレッディングはありません。

子供にio_serviceを渡すことを忘れないでください、とon_exitハンドラを使用します。

Live On Coliru

#include <boost/process.hpp> 
//#include <boost/asio.hpp> 
#include <boost/bind.hpp> 
#include <system_error> 
#include <utility> 
#include <iostream> 

namespace bp = boost::process; 

char my_buffer[1024]; 

boost::asio::io_service io; 
bp::async_pipe in_pipe(io); 

void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred); 

void schedule_read() { 
    in_pipe.async_read_some(
     boost::asio::buffer(my_buffer), 
     boost::bind(&handle_pipe_read, _1, _2)); 
} 

void handle_pipe_read(const boost::system::error_code &ec, std::size_t bytes_transferred) { 
    if (ec) 
     return; // app probably exit 

    // Do something with buffer and re-schedule 
    std::cout.write(my_buffer, bytes_transferred); 

    if (in_pipe.is_open()) 
     schedule_read(); 
} 

int main() { 
    bp::child c("/bin/ls", bp::std_out > in_pipe, 
      bp::on_exit([](int code, std::error_code ec) { 
       std::cout << "Child exited (" << code << "): " << ec.message() << std::endl; 
       in_pipe.close(); 
      }), io); 

    schedule_read(); 
    io.run(); 

    std::cout << "Service done (" << c.exit_code() << ")" << std::endl; 
} 

プリント:

a.out 
main.cpp 
Child exited (0): Success 
Service done (0) 
+0

私が気づいていない素敵な機能です。私にチェックさせて、私はあなたに戻ってきます。 –

+0

あなたのための質問があります:このboost :: process :: on_exitがどこで実行されているか知っていますか?すべてのboost :: asioハンドラで発生するので、どのスレッドでも実行できるコールバックですか? –

+0

私がテストした後も、子アプリケーションがクラッシュした場合、このハンドラは呼び出されないことがわかります。だから、クラッシュについて通知される最良の方法が何であるかまだ分かりません。アプリケーションが実行されておらず、正しく終了していない場合は例外がスローされます。 –

0

のために働いていた唯一のソリューションを私は次のとおりです

  1. スケジュールが完了は常に読み取りのために完了ハンドラをパイプ(クラッシュにより)壊れます

のスケジュールを変更していないERROR_CODEセットにchild::running()

  • を呼び出すチェック
  • を読みますboost :: error_code引数がtrueに設定されています。これにもかかわらず、boost :: error_codeが設定されていないときにもchild :: running()がfalseの場合があります。

  • 関連する問題