github.com/searKing/golang/go@v1.2.74/os/signal/signal.go (about) 1 // Copyright 2022 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package signal 6 7 import "C" 8 import ( 9 "fmt" 10 "io/ioutil" 11 "os" 12 "os/signal" 13 "path/filepath" 14 "syscall" 15 "time" 16 ) 17 18 // enhance signal.Notify with stacktrace of cgo. 19 // redirects signal log to stdout 20 func init() { 21 DumpSignalTo(syscall.Stdout) 22 // FIXME https://github.com/golang/go/issues/35814 23 //RegisterOnSignal(OnSignalHandlerFunc(func(signum os.Signal) {})) 24 25 var dumpfile string 26 if f, err := ioutil.TempFile("", "*.stacktrace.dump"); err == nil { 27 dumpfile = f.Name() 28 } else { 29 dumpfile = filepath.Join(os.TempDir(), fmt.Sprintf("stacktrace.%d.dump", time.Now().UnixNano())) 30 } 31 32 DumpStacktraceTo(dumpfile) 33 defer os.Remove(dumpfile) 34 } 35 36 type OnSignalHandler interface { 37 OnSignal(signum os.Signal) 38 } 39 40 type OnSignalHandlerFunc func(signum os.Signal) 41 42 func (f OnSignalHandlerFunc) OnSignal(signum os.Signal) { 43 f(signum) 44 } 45 46 // Notify act as signal.Notify, which invokes the Go signal handler. 47 // https://godoc.org/os/signal#hdr-Go_programs_that_use_cgo_or_SWIG 48 // Notify must be called again when one sig is called on windows system 49 // as windows is based on signal(), which will reset sig's handler to SIG_DFL before sig's handler is called 50 // While unix-like os will remain sig's handler always. 51 func Notify(c chan<- os.Signal, sigs ...os.Signal) { 52 if len(sigs) == 0 { 53 for n := 0; n < numSig; n++ { 54 sigs = append(sigs, syscall.Signal(n)) 55 } 56 } 57 signal.Notify(c, sigs...) 58 setSig(sigs...) 59 } 60 61 // DumpSignalTo redirects log to fd, -1 if not set; muted if < 0. 62 func DumpSignalTo(fd int) { 63 dumpSignalTo(fd) 64 } 65 66 // DumpStacktraceTo set dump file path of stacktrace when signal is triggered 67 // "*.stacktrace.dump" under a temp dir if not set. 68 func DumpStacktraceTo(name string) { 69 dumpStacktraceTo(name) 70 } 71 72 // DumpPreviousStacktrace dumps the previous human readable stacktrace to fd, which is set by SetSignalDumpToFd. 73 func DumpPreviousStacktrace() { 74 dumpPreviousStacktrace() 75 } 76 77 // PreviousStacktrace returns a human readable stacktrace 78 func PreviousStacktrace() string { 79 return previousStacktrace() 80 } 81 82 // SetSigInvokeChain sets a rule to raise signal to {to} and wait until {wait}, done with sleep {sleepInSeconds}s 83 func SetSigInvokeChain(to os.Signal, wait os.Signal, sleepInSeconds int, froms ...os.Signal) { 84 for _, from := range froms { 85 setSigInvokeChain(Signum(from), Signum(to), Signum(wait), sleepInSeconds) 86 } 87 }