github.com/searKing/golang/go@v1.2.74/os/signal/cgo/base_signal_handler.hpp (about)

     1  // Copyright (c) 2019 The searKing authors. All Rights Reserved.
     2  //
     3  // Use of this source code is governed by a MIT-style license
     4  // that can be found in the LICENSE file in the root of the source
     5  // tree. An additional intellectual property rights grant can be found
     6  // in the file PATENTS.  All contributing project authors may
     7  // be found in the AUTHORS file in the root of the source tree.
     8  
     9  // +build cgo
    10  
    11  #ifndef GO_OS_SIGNAL_CGO_BASE_SIGNAL_HANDLER_HPP_
    12  #define GO_OS_SIGNAL_CGO_BASE_SIGNAL_HANDLER_HPP_
    13  #include <boost/core/noncopyable.hpp>
    14  #include <boost/stacktrace.hpp>
    15  #include <cstdio>
    16  #include <cstring>
    17  #include <fstream>
    18  #include <map>
    19  #include <memory>
    20  #include <sstream>
    21  #include <string>
    22  #include <tuple>
    23  
    24  #include "write_int.hpp"
    25  
    26  namespace searking {
    27  template <class T>
    28  class BaseSignalHandler : private boost::noncopyable,
    29                            public std::enable_shared_from_this<T> {
    30   protected:
    31    BaseSignalHandler() : signal_dump_to_fd_(-1) {}
    32  
    33   public:
    34    void SetSignalDumpToFd(int fd) { signal_dump_to_fd_ = fd; }
    35  
    36    void SetSignalDumpToFd(FILE *fd) { SetSignalDumpToFd(fileno(fd)); }
    37  
    38    void SetStacktraceDumpToFile(const std::string &name) {
    39      stacktrace_dump_to_file_ = name;
    40    }
    41  
    42    void WriteSignalStacktrace(int signum) {
    43      if (signal_dump_to_fd_ >= 0) {
    44        write(signal_dump_to_fd_, "Signal received(", strlen("Signal received("));
    45        WriteInt(signal_dump_to_fd_, signum);
    46        write(signal_dump_to_fd_, ").\n", strlen(").\n"));
    47        // binary format,not human readable.mute this.
    48        //    write(signal_dump_to_fd_, "stacktrace dumped in binary format:\n",
    49        //          strlen("stacktrace dumped in binary format:\n"));
    50        //    boost::stacktrace::safe_dump_to(signal_dump_to_fd_);
    51        //    write(signal_dump_to_fd_, "\n", strlen("\n"));
    52      }
    53  
    54      if (!stacktrace_dump_to_file_.empty()) {
    55        if (signal_dump_to_fd_ >= 0) {
    56          write(signal_dump_to_fd_, "Stacktrace dumped to file: ",
    57                strlen("Stacktrace dumped to file: "));
    58          write(signal_dump_to_fd_, stacktrace_dump_to_file_.c_str(),
    59                stacktrace_dump_to_file_.length());
    60          write(signal_dump_to_fd_, ".\n", strlen(".\n"));
    61        }
    62        boost::stacktrace::safe_dump_to(stacktrace_dump_to_file_.c_str());
    63      }
    64    }
    65  
    66    ssize_t DumpPreviousStacktrace() {
    67      if (signal_dump_to_fd_ < 0) {
    68        return 0;
    69      }
    70  
    71      std::ostringstream msg;
    72      msg << "Previous run crashed:" << std::endl;
    73      msg << PreviousStacktrace();
    74  
    75      auto m = msg.str();
    76      return write(signal_dump_to_fd_, m.c_str(), m.length());
    77    }
    78    std::string PreviousStacktrace() {
    79      if (stacktrace_dump_to_file_.empty()) {
    80        return "";
    81      }
    82  
    83      std::ifstream ifs(stacktrace_dump_to_file_);
    84      if (!ifs.good()) {
    85        return "";
    86      }
    87  
    88      std::shared_ptr<int> deferFileCLose(nullptr, [&ifs](int *) {
    89        // cleaning up
    90        ifs.close();
    91      });
    92  
    93      // there is a backtrace
    94      boost::stacktrace::stacktrace st =
    95          boost::stacktrace::stacktrace::from_dump(ifs);
    96      std::ostringstream msg;
    97  
    98      msg << st << std::endl;
    99      return msg.str();
   100    }
   101  
   102    void SetSigInvokeChain(const int from, const int to, const int wait,
   103                           const int sleepInSeconds) {
   104      sig_invoke_signal_chains_[from] =
   105          std::make_tuple(from, to, wait, sleepInSeconds);
   106    }
   107  
   108    void SetSigInvokeChain(const int from, const int pipeWriter,
   109                           const int pipeReader) {
   110      sig_invoke_pipe_chains_[from] =
   111          std::make_tuple(from, pipeWriter, pipeReader);
   112    }
   113  
   114   protected:
   115    int signal_dump_to_fd_;
   116    std::string stacktrace_dump_to_file_;
   117    // <from, <from, to, wait, sleepInSeconds>>
   118    std::map<int, std::tuple<int, int, int, int>> sig_invoke_signal_chains_;
   119  
   120    // <from, <from, pipeWriter, pipeReader>>
   121    std::map<int, std::tuple<int, int, int>> sig_invoke_pipe_chains_;
   122  };
   123  }  // namespace searking
   124  #endif  // GO_OS_SIGNAL_CGO_BASE_SIGNAL_HANDLER_HPP_