github.com/searKing/golang/go@v1.2.74/os/signal/cgo/signal_handler_windows.cpp (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 // +build windows 11 12 #include "signal_handler_windows.hpp" 13 14 #include <string.h> 15 16 #include <boost/stacktrace.hpp> 17 #include <fstream> 18 #include <memory> 19 #include <sstream> 20 21 namespace searking { 22 // sig nums must be in [0,255) 23 static volatile sig_atomic_t gotSignals[256]; 24 25 SignalHandler &SignalHandler::GetInstance() { 26 static SignalHandler instance; 27 return instance; 28 } 29 30 // trigger once, and user must register this signum again 31 void SignalHandler::operator()(int signum) { 32 WriteSignalStacktrace(signum); 33 void *on_signal_ctx = on_signal_ctx_; 34 auto on_signal = on_signal_; 35 36 if (on_signal) { 37 on_signal(on_signal_ctx, signal_dump_to_fd_, signum); 38 } 39 DoSignalChan(signum); 40 41 InvokeGoSignalHandler(signum); 42 } 43 44 void SignalHandler::DoSignalChan(int signum) { 45 gotSignals[signum] = true; 46 auto it = sig_invoke_signal_chains_.find(signum); 47 if (it == sig_invoke_signal_chains_.end()) { 48 return; 49 } 50 auto &sig_chain = it->second; 51 int from = std::get<0>(sig_chain); 52 // consist validation_ 53 if (from != signum) { 54 return; 55 } 56 int to = std::get<1>(sig_chain); 57 int wait = std::get<2>(sig_chain); 58 int sleepInSeconds = std::get<3>(sig_chain); 59 if (to >= 0 && to != signum) { 60 InvokeGoSignalHandler(to); 61 } 62 if (wait >= 0 && wait != signum) { 63 gotSignals[wait] = false; 64 for (;;) { 65 bool got = gotSignals[wait]; 66 if (got) { 67 gotSignals[wait] = false; 68 break; 69 } 70 // sleep 1s at most, will awake when an unmasked signal is received 71 sleep(1); 72 } 73 } 74 if (sleepInSeconds > 0) { 75 sleep(sleepInSeconds); 76 } 77 } 78 79 void SignalHandler::InvokeGoSignalHandler(int signum) { 80 auto it = go_registered_handlers_.find(signum); 81 if (it != go_registered_handlers_.end()) { 82 SignalHandlerSignalHandler signalHandler = it->second; 83 ::signal(signum, signalHandler); 84 ::raise(signum); 85 } 86 } 87 88 void SignalHandler::RegisterOnSignal( 89 std::function<void(void *ctx, int fd, int signum)> callback, void *ctx) { 90 on_signal_ctx_ = ctx; 91 on_signal_ = callback; 92 } 93 94 void SignalHandler::SetGoRegisteredSignalHandlersIfEmpty( 95 int signum, SignalHandlerSignalHandler handler) { 96 auto it = go_registered_handlers_.find(signum); 97 98 // register once, avoid go's signal actions are lost. 99 if (it == go_registered_handlers_.end()) { 100 go_registered_handlers_[signum] = handler; 101 } 102 } 103 104 int SignalHandler::SetSig(int signum) { 105 SignalHandlerSignalHandler handler = [](int signum) { 106 GetInstance()(signum); 107 }; 108 109 return SetSig(signum, handler); 110 } 111 112 int SignalHandler::SetSig(int signum, SignalHandlerSignalHandler handler) { 113 SignalHandlerSignalHandler prev_handler = ::signal(signum, SIG_DFL); 114 115 if (SIG_ERR == prev_handler) { 116 return -1; 117 } 118 GetInstance().SetGoRegisteredSignalHandlersIfEmpty(signum, prev_handler); 119 120 ::signal(signum, handler); 121 return 0; 122 } 123 124 } // namespace searking