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  }