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