Sigaction和将Linux代码移植到Windows

11

我正在尝试将专为Linux开发的caffe源代码移植到Windows环境。问题出现在signal_handler.cppsignal_handler.h中的sigaction结构上。以下是源代码。

我的问题是,哪个库或代码替换可以使这个sigaction在Windows中正常工作。

///头文件

#ifndef INCLUDE_CAFFE_UTIL_SIGNAL_HANDLER_H_
#define INCLUDE_CAFFE_UTIL_SIGNAL_HANDLER_H_

#include "caffe/proto/caffe.pb.h"
#include "caffe/solver.hpp"

namespace caffe {

class SignalHandler {
 public:
  // Contructor. Specify what action to take when a signal is received.
  SignalHandler(SolverAction::Enum SIGINT_action,
                SolverAction::Enum SIGHUP_action);
  ~SignalHandler();
  ActionCallback GetActionFunction();
 private:
  SolverAction::Enum CheckForSignals() const;
  SolverAction::Enum SIGINT_action_;
  SolverAction::Enum SIGHUP_action_;
};

}  // namespace caffe

#endif  // INCLUDE_CAFFE_UTIL_SIGNAL_HANDLER_H_

///源文件

    #include <boost/bind.hpp>
    #include <glog/logging.h>

    #include <signal.h>
    #include <csignal>

    #include "caffe/util/signal_handler.h"

    namespace {
      static volatile sig_atomic_t got_sigint = false;
      static volatile sig_atomic_t got_sighup = false;
      static bool already_hooked_up = false;

      void handle_signal(int signal) {
        switch (signal) {
        case SIGHUP:
          got_sighup = true;
          break;
        case SIGINT:
          got_sigint = true;
          break;
        }
      }

      void HookupHandler() {
        if (already_hooked_up) {
          LOG(FATAL) << "Tried to hookup signal handlers more than once.";
        }
        already_hooked_up = true;

        struct sigaction sa;
        // Setup the handler
        sa.sa_handler = &handle_signal;
        // Restart the system call, if at all possible
        sa.sa_flags = SA_RESTART;
        // Block every signal during the handler
        sigfillset(&sa.sa_mask);
        // Intercept SIGHUP and SIGINT
        if (sigaction(SIGHUP, &sa, NULL) == -1) {
          LOG(FATAL) << "Cannot install SIGHUP handler.";
        }
        if (sigaction(SIGINT, &sa, NULL) == -1) {
          LOG(FATAL) << "Cannot install SIGINT handler.";
        }
      }

      // Set the signal handlers to the default.
      void UnhookHandler() {
        if (already_hooked_up) {
          struct sigaction sa;
          // Setup the sighub handler
          sa.sa_handler = SIG_DFL;
          // Restart the system call, if at all possible
          sa.sa_flags = SA_RESTART;
          // Block every signal during the handler
          sigfillset(&sa.sa_mask);
          // Intercept SIGHUP and SIGINT
          if (sigaction(SIGHUP, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGHUP handler.";
          }
          if (sigaction(SIGINT, &sa, NULL) == -1) {
            LOG(FATAL) << "Cannot uninstall SIGINT handler.";
          }

          already_hooked_up = false;
        }
      }

      // Return true iff a SIGINT has been received since the last time this
      // function was called.
      bool GotSIGINT() {
        bool result = got_sigint;
        got_sigint = false;
        return result;
      }

      // Return true iff a SIGHUP has been received since the last time this
      // function was called.
      bool GotSIGHUP() {
        bool result = got_sighup;
        got_sighup = false;
        return result;
      }
    }  // namespace

    namespace caffe {

    SignalHandler::SignalHandler(SolverAction::Enum SIGINT_action,
                                 SolverAction::Enum SIGHUP_action):
      SIGINT_action_(SIGINT_action),
      SIGHUP_action_(SIGHUP_action) {
      HookupHandler();
    }

    SignalHandler::~SignalHandler() {
      UnhookHandler();
    }

    SolverAction::Enum SignalHandler::CheckForSignals() const {
      if (GotSIGHUP()) {
        return SIGHUP_action_;
      }
      if (GotSIGINT()) {
        return SIGINT_action_;
      }
      return SolverAction::NONE;
    }

    // Return the function that the solver can use to find out if a snapshot or
    // early exit is being requested.
    ActionCallback SignalHandler::GetActionFunction() {
      return boost::bind(&SignalHandler::CheckForSignals, this);
    }

    }  // namespace caffe

错误如下:
.\src\caffe\util\signal_handler.cpp(39): error C2065: 'SIGHUP' : undeclared identifier
1>..\src\caffe\util\signal_handler.cpp(42): error C2514: '`anonymous-namespace'::HookupHandler::sigaction' : class has no constructors
1>          ..\src\caffe\util\signal_handler.cpp(31) : see declaration of '`anonymous-namespace'::HookupHandler::sigaction'
1>..\src\caffe\util\signal_handler.cpp(50): error C2079: 'sa' uses undefined struct '`anonymous-namespace'::UnhookHandler::sigaction'
1>..\src\caffe\util\signal_handler.cpp(52): error C2228: left of '.sa_handler' must have class/struct/union
1>          type is 'int'
1>..\src\caffe\util\signal_handler.cpp(54): error C2228: left of '.sa_flags' must have class/struct/union
1>          type is 'int'
1>..\src\caffe\util\signal_handler.cpp(54): error C2065: 'SA_RESTART' : undeclared identifier
1>..\src\caffe\util\signal_handler.cpp(56): error C2228: left of '.sa_mask' must have class/struct/union

如果仍然相关,以下的 GitHub 代码库将 Caffe 移植到 Windows 平台:https://github.com/happynear/caffe-windows - rkellerm
有一个 ANSI C 的 signal() 函数,可能可以处理您想要的中断。您想要的常量在 signal.h 或 C++ 中的 <csignal> 中。 - seattlecpp
2个回答

10

根据 @nneonneo 提供的信息:

void handle_signal(int signal) {
    switch (signal) {
#ifdef _WIN32
    case SIGTERM:
    case SIGABRT:
    case SIGBREAK:
#else
    case SIGHUP:
#endif
      got_sighup = true;
      break;
    case SIGINT:
      got_sigint = true;
      break;
    }
  }
void HookupHandler() {
    if (already_hooked_up) {
      LOG(FATAL) << "Tried to hookup signal handlers more than once.";
    }
    already_hooked_up = true;
#ifdef _WIN32
    signal(SIGINT, handle_signal);
    signal(SIGTERM, handle_signal);
    signal(SIGABRT, handle_signal);
#else
    struct sigaction sa;
    // Setup the handler
    sa.sa_handler = &handle_signal;
    // Restart the system call, if at all possible
    sa.sa_flags = SA_RESTART;
    // Block every signal during the handler
    sigfillset(&sa.sa_mask);
    // Intercept SIGHUP and SIGINT
    if (sigaction(SIGHUP, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGHUP handler.";
    }
    if (sigaction(SIGINT, &sa, NULL) == -1) {
      LOG(FATAL) << "Cannot install SIGINT handler.";
    }
#endif
  }
 void UnhookHandler() {
    if (already_hooked_up) {
#ifdef _WIN32
        signal(SIGINT, SIG_DFL);
        signal(SIGTERM, SIG_DFL);
        signal(SIGABRT, SIG_DFL);
#else
      struct sigaction sa;
      // Setup the sighub handler
      sa.sa_handler = SIG_DFL;
      // Restart the system call, if at all possible
      sa.sa_flags = SA_RESTART;
      // Block every signal during the handler
      sigfillset(&sa.sa_mask);
      // Intercept SIGHUP and SIGINT
      if (sigaction(SIGHUP, &sa, NULL) == -1) {
        LOG(FATAL) << "Cannot uninstall SIGHUP handler.";
      }
      if (sigaction(SIGINT, &sa, NULL) == -1) {
        LOG(FATAL) << "Cannot uninstall SIGINT handler.";
      }
#endif

      already_hooked_up = false;
    }
  }

9

sigaction是UNIX信号API的一部分。Windows仅提供signal,不支持SIGHUP或任何标志(例如SA_RESTART)。但基本的支持仍然存在,因此如果仅使用signal(而不是sigaction),代码仍应该能够正常工作。


我无法替换sigaction。但是我能否替换功能,我的意思是由sigaction支持的操作将被signal替换。Signal在Windows中提供。你觉得呢? - batuman
是的,目前的解决方案就是将那个sigaction函数注释掉,因为我暂时没有时间解决它。Windows不提供SIGHUP标志,我会用一个Windows支持且有用的标志来替换它。 - batuman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接