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  }