github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/signal/signal_linux.go (about)

     1  // +build linux
     2  
     3  // Signal handling for Linux only.
     4  package signal
     5  
     6  // Copyright 2013-2018 Docker, Inc.
     7  
     8  // NOTE: this package has originally been copied from github.com/docker/docker.
     9  
    10  import (
    11  	"fmt"
    12  	"os"
    13  	"os/signal"
    14  	"strconv"
    15  	"strings"
    16  	"syscall"
    17  
    18  	"golang.org/x/sys/unix"
    19  )
    20  
    21  const (
    22  	sigrtmin = 34
    23  	sigrtmax = 64
    24  
    25  	SIGWINCH = syscall.SIGWINCH // For cross-compilation with Windows
    26  )
    27  
    28  // signalMap is a map of Linux signals.
    29  var signalMap = map[string]syscall.Signal{
    30  	"ABRT":     unix.SIGABRT,
    31  	"ALRM":     unix.SIGALRM,
    32  	"BUS":      unix.SIGBUS,
    33  	"CHLD":     unix.SIGCHLD,
    34  	"CLD":      unix.SIGCLD,
    35  	"CONT":     unix.SIGCONT,
    36  	"FPE":      unix.SIGFPE,
    37  	"HUP":      unix.SIGHUP,
    38  	"ILL":      unix.SIGILL,
    39  	"INT":      unix.SIGINT,
    40  	"IO":       unix.SIGIO,
    41  	"IOT":      unix.SIGIOT,
    42  	"KILL":     unix.SIGKILL,
    43  	"PIPE":     unix.SIGPIPE,
    44  	"POLL":     unix.SIGPOLL,
    45  	"PROF":     unix.SIGPROF,
    46  	"PWR":      unix.SIGPWR,
    47  	"QUIT":     unix.SIGQUIT,
    48  	"SEGV":     unix.SIGSEGV,
    49  	"STKFLT":   unix.SIGSTKFLT,
    50  	"STOP":     unix.SIGSTOP,
    51  	"SYS":      unix.SIGSYS,
    52  	"TERM":     unix.SIGTERM,
    53  	"TRAP":     unix.SIGTRAP,
    54  	"TSTP":     unix.SIGTSTP,
    55  	"TTIN":     unix.SIGTTIN,
    56  	"TTOU":     unix.SIGTTOU,
    57  	"URG":      unix.SIGURG,
    58  	"USR1":     unix.SIGUSR1,
    59  	"USR2":     unix.SIGUSR2,
    60  	"VTALRM":   unix.SIGVTALRM,
    61  	"WINCH":    unix.SIGWINCH,
    62  	"XCPU":     unix.SIGXCPU,
    63  	"XFSZ":     unix.SIGXFSZ,
    64  	"RTMIN":    sigrtmin,
    65  	"RTMIN+1":  sigrtmin + 1,
    66  	"RTMIN+2":  sigrtmin + 2,
    67  	"RTMIN+3":  sigrtmin + 3,
    68  	"RTMIN+4":  sigrtmin + 4,
    69  	"RTMIN+5":  sigrtmin + 5,
    70  	"RTMIN+6":  sigrtmin + 6,
    71  	"RTMIN+7":  sigrtmin + 7,
    72  	"RTMIN+8":  sigrtmin + 8,
    73  	"RTMIN+9":  sigrtmin + 9,
    74  	"RTMIN+10": sigrtmin + 10,
    75  	"RTMIN+11": sigrtmin + 11,
    76  	"RTMIN+12": sigrtmin + 12,
    77  	"RTMIN+13": sigrtmin + 13,
    78  	"RTMIN+14": sigrtmin + 14,
    79  	"RTMIN+15": sigrtmin + 15,
    80  	"RTMAX-14": sigrtmax - 14,
    81  	"RTMAX-13": sigrtmax - 13,
    82  	"RTMAX-12": sigrtmax - 12,
    83  	"RTMAX-11": sigrtmax - 11,
    84  	"RTMAX-10": sigrtmax - 10,
    85  	"RTMAX-9":  sigrtmax - 9,
    86  	"RTMAX-8":  sigrtmax - 8,
    87  	"RTMAX-7":  sigrtmax - 7,
    88  	"RTMAX-6":  sigrtmax - 6,
    89  	"RTMAX-5":  sigrtmax - 5,
    90  	"RTMAX-4":  sigrtmax - 4,
    91  	"RTMAX-3":  sigrtmax - 3,
    92  	"RTMAX-2":  sigrtmax - 2,
    93  	"RTMAX-1":  sigrtmax - 1,
    94  	"RTMAX":    sigrtmax,
    95  }
    96  
    97  // ParseSignal translates a string to a valid syscall signal.
    98  // It returns an error if the signal map doesn't include the given signal.
    99  func ParseSignal(rawSignal string) (syscall.Signal, error) {
   100  	s, err := strconv.Atoi(rawSignal)
   101  	if err == nil {
   102  		if s == 0 {
   103  			return -1, fmt.Errorf("invalid signal: %s", rawSignal)
   104  		}
   105  		return syscall.Signal(s), nil
   106  	}
   107  	sig, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
   108  	if !ok {
   109  		return -1, fmt.Errorf("invalid signal: %s", rawSignal)
   110  	}
   111  	return sig, nil
   112  }
   113  
   114  // CatchAll catches all signals and relays them to the specified channel.
   115  func CatchAll(sigc chan os.Signal) {
   116  	var handledSigs []os.Signal
   117  	for _, s := range signalMap {
   118  		handledSigs = append(handledSigs, s)
   119  	}
   120  	signal.Notify(sigc, handledSigs...)
   121  }
   122  
   123  // StopCatch stops catching the signals and closes the specified channel.
   124  func StopCatch(sigc chan os.Signal) {
   125  	signal.Stop(sigc)
   126  	close(sigc)
   127  }
   128  
   129  // ParseSignalNameOrNumber translates a string to a valid syscall signal.  Input
   130  // can be a name or number representation i.e. "KILL" "9"
   131  func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) {
   132  	basename := strings.TrimPrefix(rawSignal, "-")
   133  	s, err := ParseSignal(basename)
   134  	if err == nil {
   135  		return s, nil
   136  	}
   137  	for k, v := range signalMap {
   138  		if k == strings.ToUpper(basename) {
   139  			return v, nil
   140  		}
   141  	}
   142  	return -1, fmt.Errorf("invalid signal: %s", basename)
   143  }