pkg.re/essentialkaos/ek.10@v12.41.0+incompatible/signal/signal.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  // Package signal provides methods for handling POSIX signals
     5  package signal
     6  
     7  // ////////////////////////////////////////////////////////////////////////////////// //
     8  //                                                                                    //
     9  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
    10  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
    11  //                                                                                    //
    12  // ////////////////////////////////////////////////////////////////////////////////// //
    13  
    14  import (
    15  	"fmt"
    16  	"os"
    17  	"os/signal"
    18  	"strings"
    19  	"syscall"
    20  )
    21  
    22  // ////////////////////////////////////////////////////////////////////////////////// //
    23  
    24  // Signal codes
    25  const (
    26  	ABRT   = syscall.SIGABRT   // ABRT signal code
    27  	ALRM   = syscall.SIGALRM   // ALRM signal code
    28  	BUS    = syscall.SIGBUS    // BUS signal code
    29  	CHLD   = syscall.SIGCHLD   // CHLD signal code
    30  	CONT   = syscall.SIGCONT   // CONT signal code
    31  	FPE    = syscall.SIGFPE    // FPE signal code
    32  	HUP    = syscall.SIGHUP    // HUP signal code
    33  	ILL    = syscall.SIGILL    // ILL signal code
    34  	INT    = syscall.SIGINT    // INT signal code
    35  	IO     = syscall.SIGIO     // IO signal code
    36  	IOT    = syscall.SIGIOT    // IOT signal code
    37  	KILL   = syscall.SIGKILL   // KILL signal code
    38  	PIPE   = syscall.SIGPIPE   // PIPE signal code
    39  	PROF   = syscall.SIGPROF   // PROF signal code
    40  	QUIT   = syscall.SIGQUIT   // QUIT signal code
    41  	SEGV   = syscall.SIGSEGV   // SEGV signal code
    42  	STOP   = syscall.SIGSTOP   // STOP signal code
    43  	SYS    = syscall.SIGSYS    // SYS signal code
    44  	TERM   = syscall.SIGTERM   // TERM signal code
    45  	TRAP   = syscall.SIGTRAP   // TRAP signal code
    46  	TSTP   = syscall.SIGTSTP   // TSTP signal code
    47  	TTIN   = syscall.SIGTTIN   // TTIN signal code
    48  	TTOU   = syscall.SIGTTOU   // TTOU signal code
    49  	URG    = syscall.SIGURG    // URG signal code
    50  	USR1   = syscall.SIGUSR1   // USR1 signal code
    51  	USR2   = syscall.SIGUSR2   // USR2 signal code
    52  	VTALRM = syscall.SIGVTALRM // VTALRM signal code
    53  	WINCH  = syscall.SIGWINCH  // WINCH signal code
    54  	XCPU   = syscall.SIGXCPU   // XCPU signal code
    55  	XFSZ   = syscall.SIGXFSZ   // XFSZ signal code
    56  )
    57  
    58  // ////////////////////////////////////////////////////////////////////////////////// //
    59  
    60  // Handlers is map signal → handler
    61  type Handlers map[os.Signal]func()
    62  
    63  // ////////////////////////////////////////////////////////////////////////////////// //
    64  
    65  // Send sends given signal to process
    66  func Send(pid int, signal syscall.Signal) error {
    67  	return syscall.Kill(pid, signal)
    68  }
    69  
    70  // ////////////////////////////////////////////////////////////////////////////////// //
    71  
    72  // Track catches signal and executes handler for this signal
    73  func (h Handlers) Track() {
    74  	c := make(chan os.Signal)
    75  
    76  	for s := range h {
    77  		signal.Notify(c, s)
    78  	}
    79  
    80  	go func() {
    81  		for {
    82  			sig := <-c
    83  
    84  			handler := h[sig]
    85  
    86  			if handler != nil {
    87  				handler()
    88  			}
    89  		}
    90  	}()
    91  }
    92  
    93  // TrackAsync catches signal and executes async handler for this signal
    94  func (h Handlers) TrackAsync() {
    95  	c := make(chan os.Signal)
    96  
    97  	for s := range h {
    98  		signal.Notify(c, s)
    99  	}
   100  
   101  	go func() {
   102  		for {
   103  			sig := <-c
   104  
   105  			handler := h[sig]
   106  
   107  			if handler != nil {
   108  				go handler()
   109  			}
   110  		}
   111  	}()
   112  }
   113  
   114  // ////////////////////////////////////////////////////////////////////////////////// //
   115  
   116  // codebeat:disable[LOC,ABC]
   117  
   118  // GetByName returns signal with given name
   119  func GetByName(name string) (syscall.Signal, error) {
   120  	switch strings.ToUpper(name) {
   121  	case "SIGABRT", "ABRT":
   122  		return ABRT, nil
   123  	case "SIGALRM", "ALRM":
   124  		return ALRM, nil
   125  	case "SIGBUS", "BUS":
   126  		return BUS, nil
   127  	case "SIGCHLD", "CHLD":
   128  		return CHLD, nil
   129  	case "SIGCONT", "CONT":
   130  		return CONT, nil
   131  	case "SIGFPE", "FPE":
   132  		return FPE, nil
   133  	case "SIGHUP", "HUP":
   134  		return HUP, nil
   135  	case "SIGILL", "ILL":
   136  		return ILL, nil
   137  	case "SIGINT", "INT":
   138  		return INT, nil
   139  	case "SIGIO", "IO":
   140  		return IO, nil
   141  	case "SIGIOT", "IOT":
   142  		return IOT, nil
   143  	case "SIGKILL", "KILL":
   144  		return KILL, nil
   145  	case "SIGPIPE", "PIPE":
   146  		return PIPE, nil
   147  	case "SIGPROF", "PROF":
   148  		return PROF, nil
   149  	case "SIGQUIT", "QUIT":
   150  		return QUIT, nil
   151  	case "SIGSEGV", "SEGV":
   152  		return SEGV, nil
   153  	case "SIGSTOP", "STOP":
   154  		return STOP, nil
   155  	case "SIGSYS", "SYS":
   156  		return SYS, nil
   157  	case "SIGTERM", "TERM":
   158  		return TERM, nil
   159  	case "SIGTRAP", "TRAP":
   160  		return TRAP, nil
   161  	case "SIGTSTP", "TSTP":
   162  		return TSTP, nil
   163  	case "SIGTTIN", "TTIN":
   164  		return TTIN, nil
   165  	case "SIGTTOU", "TTOU":
   166  		return TTOU, nil
   167  	case "SIGURG", "URG":
   168  		return URG, nil
   169  	case "SIGUSR1", "USR1":
   170  		return USR1, nil
   171  	case "SIGUSR2", "USR2":
   172  		return USR2, nil
   173  	case "SIGVTALRM", "VTALRM":
   174  		return VTALRM, nil
   175  	case "SIGWINCH", "WINCH":
   176  		return WINCH, nil
   177  	case "SIGXCPU", "XCPU":
   178  		return XCPU, nil
   179  	case "SIGXFSZ", "XFSZ":
   180  		return XFSZ, nil
   181  	}
   182  
   183  	return syscall.Signal(-1), fmt.Errorf("Unknown signal name %s", name)
   184  }
   185  
   186  // GetByCode returns signal with given code
   187  func GetByCode(code int) (syscall.Signal, error) {
   188  	switch code {
   189  	case 1:
   190  		return HUP, nil
   191  	case 2:
   192  		return INT, nil
   193  	case 3:
   194  		return QUIT, nil
   195  	case 4:
   196  		return ILL, nil
   197  	case 5:
   198  		return TRAP, nil
   199  	case 6:
   200  		return ABRT, nil
   201  	case 8:
   202  		return FPE, nil
   203  	case 9:
   204  		return KILL, nil
   205  	case 10:
   206  		return BUS, nil
   207  	case 11:
   208  		return SEGV, nil
   209  	case 12:
   210  		return SYS, nil
   211  	case 13:
   212  		return PIPE, nil
   213  	case 14:
   214  		return ALRM, nil
   215  	case 15:
   216  		return TERM, nil
   217  	case 16:
   218  		return USR1, nil
   219  	case 17:
   220  		return USR2, nil
   221  	case 18:
   222  		return CHLD, nil
   223  	case 20:
   224  		return TSTP, nil
   225  	case 21:
   226  		return URG, nil
   227  	case 23:
   228  		return STOP, nil
   229  	case 25:
   230  		return CONT, nil
   231  	case 26:
   232  		return TTIN, nil
   233  	case 27:
   234  		return TTOU, nil
   235  	case 28:
   236  		return VTALRM, nil
   237  	case 29:
   238  		return PROF, nil
   239  	case 30:
   240  		return XCPU, nil
   241  	case 31:
   242  		return XFSZ, nil
   243  	}
   244  
   245  	return syscall.Signal(-1), fmt.Errorf("Unknown signal code %d", code)
   246  }
   247  
   248  // codebeat:enable[LOC,ABC]
   249  
   250  // ////////////////////////////////////////////////////////////////////////////////// //