비동기 모드에서 부스트 프로세스를 사용하여 시간 제한이있는 하위 프로세스를 실행하는 클래스 구현

다음 코드에서 다음 코드를 실행하는 프로그램을 구현하려고합니다. 처리하고 반환 코드 인 stdoutstderr를 반환합니다. 또한 자식 프로세스가 종료되는 시간 초과 개념이 있습니다. 이 클래스는 멀티 스레드 애플리케이션의 일부로 사용됩니다.

#ifndef PROCESS_H_ #define PROCESS_H_ //Header #include <chrono> #include <thread> #include <iostream> #include <boost/process.hpp> #include <boost/asio.hpp namespace bp = boost::process; class Proces { public: Process(const std::string& cmd, const int timeout); void run(); int getReturnStatus(); //Must be only called after run() exits std::string getStdOut(); //Must be only called after run() exits std::string getStdErr(); //Must be only called after run() exits bool wasKilled(); //Must be only called after run() exits private: void initLog(); void timeoutHandler(const boost::system::error_code& ec); void kill(); const std::string command; const int timeout; int returnStatus; std::string stdOut; std::string stdErr; bool killed; bool stopped; boost::process::group group; boost::asio::io_context ioc; boost::asio::deadline_timer deadline_timer; }; #endif //Source #include "Process.h" Process::Process(const std::string& cmd, const int timeout): command(cmd), timeout(timeout), returnStatus(0), stdOut(""), stdErr(""), killed(false), stopped(false), ioc(), deadline_timer(ioc) { } void Process::timeoutHandler(const boost::system::error_code& ec) { if (stopped || ec == boost::asio::error::operation_aborted) { return; } std::cout << "Time Up!"<< std::endl; kill(); deadline_timer.expires_at(boost::posix_time::pos_infin); } void Process::run() { std::future<std::string> dataOut; std::future<std::string> dataErr; std::cout << "Running command: " << command << std::endl; bp::child c(command, bp::std_in.close(), bp::std_out > dataOut, bp::std_err > dataErr, ioc, group, bp::on_exit([=](int e, const std::error_code& ec) { std::cout << "on_exit: " << ec.message() << " -> " << e << std::endl; deadline_timer.cancel(); returnStatus = e; })); deadline_timer.expires_from_now(boost::posix_time::seconds(timeout)); deadline_timer.async_wait(std::bind(&Process::timeoutHandler, this, std::placeholders::_1)); ioc.run(); c.wait(); stdOut = dataOut.get(); stdErr = dataErr.get(); } //Must be only called after run() exits int Process::getReturnStatus() { return returnStatus; } //Must be only called after run() exits std::string Process::getStdOut() { return stdOut; } //Must be only called after run() exits std::string Process::getStdErr() { return stdErr; } void Process::kill() { std::error_code ec; group.terminate(ec); if(ec) { std::cout << "Error occurred while trying to kill the process: " << ec.message(); throw std::runtime_error(ec.message()); } std::cout << "Killed the process and all its descendants" << std::endl; killed = true; stopped = true; } //Must be only called after run() exits bool Process::wasKilled() { return killed; } 

다음은 테스트에 사용하는 코드입니다.

#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE ProcessTest #include <boost/test/unit_test.hpp> #include "../src/Process.h" BOOST_AUTO_TEST_CASE( ProcessTest ) { const std::vector<std::string> commands = { "ls" , "pwd" , "uname -a" , "cat /proc/cpuinfo" , "wget https://dl.google.com/dl/earth/client/current/google-earth-pro-stable-current.x86_64.rpm"}; for(const auto& cmd: commands) { Process p(cmd, 3600); p.run(); BOOST_CHECK( p.getReturnStatus() == 0); // #1 continues on error } const std::vector<std::string> commandsThatShouldFail = { "ls doesnotexit" , "cat /proc/doesnotexist" , "wget https://dl.google.com/dl/earth/client/current/doesnotxist.rpm"}; for(const auto& cmd: commandsThatShouldFail) { Process p(cmd, 3600); p.run(); BOOST_CHECK( p.getReturnStatus() != 0); // #1 continues on error } } 

귀중한 의견과 제안을 제공해주십시오.

댓글

  • 코드 검토에 오신 것을 환영합니다! 프로그램을 구현하려고 '라고 말합니다. 지금까지 작동합니까? 코드에 대한 우려 사항이 있습니까? 코드가 의도 한대로 작동하는 한 ' ' t는 괜찮습니다.
  • @Mast 코드는 내가 테스트 한 사례에서 작동합니다. 하지만 경쟁 조건과 기타 버그가 있는지 궁금합니다.
  • 좋습니다! 이러한 테스트를 포함 할 수 있습니까?

답변

아직도 , 그래서 아마도 이것이 잘못되었습니다. 그러나 ios.run() 이후에 c.wait()가 정말로 필요합니까?

문서 , io_context이 완료 될 때까지 ios.run()에서 제어가 차단되거나 deadline_timer가 만료됩니다.

답변

누락 된 테스트

I 시간 초과해야하는 명령에 대한 테스트는 표시되지 않습니다. 1sleep 2 일 수 있습니다. >.보다 엄격한 테스트는 모든 신호 (무시할 수있는 신호)를 무시하는 명령입니다. SIGTERM가 작동하지 않는 경우 SIGKILL 결국.

데이터 기반 테스트

테스트 케이스 내에서 루프를보고 싶지 않습니다. Boost Test에는 다른 데이터로 테스트를 반복합니까? 대부분의 테스트 프레임 워크는 그렇습니다. 부스트에서 가져옵니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다