github.com/wfusion/gofusion@v1.1.14/http/gracefully/signal_windows.go (about)

     1  package gracefully
     2  
     3  import (
     4  	"log"
     5  	"os"
     6  	"os/signal"
     7  	"syscall"
     8  )
     9  
    10  const (
    11  	ERROR_INVALID_HANDLE = syscall.Errno(6)
    12  )
    13  
    14  var (
    15  	hookableSignals []os.Signal
    16  )
    17  
    18  func init() {
    19  	hookableSignals = []os.Signal{
    20  		syscall.SIGHUP,
    21  		syscall.SIGINT,
    22  		syscall.SIGQUIT,
    23  		syscall.SIGTERM,
    24  	}
    25  }
    26  
    27  func newSignalHookFunc() map[int]map[os.Signal][]func() {
    28  	return map[int]map[os.Signal][]func(){
    29  		PreSignal: {
    30  			syscall.SIGHUP:  []func(){},
    31  			syscall.SIGINT:  []func(){},
    32  			syscall.SIGQUIT: []func(){},
    33  			syscall.SIGTERM: []func(){},
    34  		},
    35  		PostSignal: {
    36  			syscall.SIGHUP:  []func(){},
    37  			syscall.SIGINT:  []func(){},
    38  			syscall.SIGQUIT: []func(){},
    39  			syscall.SIGTERM: []func(){},
    40  		},
    41  	}
    42  }
    43  
    44  // handleSignals listens for os Signals and calls any hooked in function that the
    45  // user had registered with the signal.
    46  func (e *endlessServer) handleSignals() {
    47  	var sig os.Signal
    48  
    49  	signal.Notify(
    50  		e.sigChan,
    51  		hookableSignals...,
    52  	)
    53  
    54  	pid := syscall.Getpid()
    55  	for {
    56  		select {
    57  		case sig = <-e.sigChan:
    58  		case <-e.close:
    59  			return
    60  		}
    61  
    62  		e.signalHooks(PreSignal, sig)
    63  		switch sig {
    64  		case syscall.SIGHUP:
    65  			signal.Stop(e.sigChan)
    66  			close(e.sigChan)
    67  			log.Println(pid, "[Common] endless received SIGHUP. forking...")
    68  			if err := e.fork(); err != nil {
    69  				log.Println("[Common] endless fork err:", err)
    70  			}
    71  			return
    72  		case syscall.SIGINT:
    73  			signal.Stop(e.sigChan)
    74  			close(e.sigChan)
    75  			log.Println(pid, "[Common] endless received SIGINT.")
    76  			e.Shutdown()
    77  			return
    78  		case syscall.SIGQUIT:
    79  			signal.Stop(e.sigChan)
    80  			close(e.sigChan)
    81  			log.Println(pid, "[Common] endless received SIGQUIT.")
    82  			e.Shutdown()
    83  			return
    84  		case syscall.SIGTERM:
    85  			signal.Stop(e.sigChan)
    86  			close(e.sigChan)
    87  			log.Println(pid, "[Common] endless received SIGTERM.")
    88  			e.Shutdown()
    89  			return
    90  		default:
    91  			log.Printf("[Common] endless received %v: nothing we care about...\n", sig)
    92  		}
    93  		e.signalHooks(PostSignal, sig)
    94  	}
    95  }
    96  
    97  func (e *endlessListener) Close() error {
    98  	if e.stopped {
    99  		return ERROR_INVALID_HANDLE
   100  	}
   101  
   102  	e.stopped = true
   103  	return e.Listener.Close()
   104  }
   105  
   106  func syscallKill(ppid int) (err error) {
   107  	handle, err := syscall.OpenProcess(syscall.PROCESS_TERMINATE, false, uint32(ppid))
   108  	if err != nil {
   109  		return err
   110  	}
   111  	defer func() {
   112  		_ = syscall.CloseHandle(handle)
   113  	}()
   114  
   115  	return syscall.TerminateProcess(handle, 1)
   116  }