Skip to content
Snippets Groups Projects
ScriptedInitialisationHandler.cc 2.73 KiB
Newer Older
#include "ScriptedInitialisationHandler.h"
#include "DeviceModule.h"

#include <boost/process.hpp>
#include <functional>
namespace bp = boost::process;

namespace ChimeraTK {

  /**********************************************************************************************************************/

  ScriptedInitHandler::ScriptedInitHandler(EntityOwner* owner, const std::string& name, const std::string& description,
      const std::string& command, DeviceModule& deviceModule, const std::string& outputName,
      unsigned int errorGracePeriod)
  : ApplicationModule(owner, name, description), _command(command), _deviceAlias(deviceModule.getDeviceAliasOrURI()),
    _outputName(outputName), _errorGracePeriod(errorGracePeriod) {
    deviceModule.addInitialisationHandler(std::bind(&ScriptedInitHandler::doInit, this));
  }
  /**********************************************************************************************************************/

  void ScriptedInitHandler::doInit() {
    std::string output;
    _scriptOutput.value = "";
    _scriptOutput.value.write();

    try {
      bp::ipstream out;
      bp::child initScript(_command, (bp::std_out & bp::std_err) > out);
      std::string line;
      // Publish every line that is read from the script. It is appended to the output string
      // such that a growing message is published.
      // For debugging it is important to get the intermediate information. In case the script gets stuck
      // you want to know what has already been printed.
      while(initScript.running() && std::getline(out, line)) {
        output += line + "\n";
        _scriptOutput.value = output;
        _scriptOutput.value.write();
      }
      initScript.wait();
      if(initScript.exit_code() != 0) {
        output += "!!! " + _deviceAlias + " initialisation FAILED!";
        _scriptOutput.value = output;
        _scriptOutput.value.write();
        if(!_lastFailed) {
          std::cerr << output << std::endl;
        }
        _lastFailed = true;
        std::this_thread::sleep_for(std::chrono::seconds(_errorGracePeriod));
        throw ChimeraTK::runtime_error(_deviceAlias + " initialisation failed.");
      }
      else {
        output += _deviceAlias + " initialisation SUCCESS!";
        _scriptOutput.value = output;
        _scriptOutput.value.write();
        std::cerr << output << std::endl;
    catch(bp::process_error& e) {
      // this
      throw ChimeraTK::logic_error("Caught boost::process::process_error while executing \"" + _command +
          "\" for device " + _deviceAlias + ": " + e.what());
    }
  }

  /**********************************************************************************************************************/
} // namespace ChimeraTK