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