How to capture arbitrary UNIX signals in Go

Issue

I can capture signals in go with signal package but how can I capture signals from 34 (SIGRTMIN) to 64 (SIGRTMAX) inclusively (link)? Golang calls them "signal 34", "signal 64" etc. but that’s beyond the point. When I run "pkill -34" I want my application to notice it.

I can capture them when I capture all signals:

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan)

However I don’t want to catch all signals, I want only those that I mentioned before.

I’m also aware that I can capture individual signals like:

signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)

But that requires signal constants and I can’t find constants that correspond to signals that I want to capture. Any ideas?

Solution

Short answer:

you can just declare new signals as typed constants of type syscall.Signal:

const (
    SIGRTMIN = syscall.Signal(0x22)
)

Long answer (how it works):

The signal.Notify function signature is:

Notify(c chan<- os.Signal, sig ...os.Signal)

where os.Signal is an interface defined as such:

// A Signal represents an operating system signal.
// The usual underlying implementation is operating system-dependent:
// on Unix it is syscall.Signal.
type Signal interface {
    String() string
    Signal() // to distinguish from other Stringers
}

Normally you would use the signal.Notify function as in your example:

signal.Notify(sigChan, os.Interrupt, syscall.SIGPOOL, syscall.SIGCLD ...)

So if we go check the implementation of those constants in the syscall package we see:

SIGKILL   = Signal(0x9)

where this Signal from the syscall package is a defined type:

// A Signal is a number describing a process signal.
// It implements the os.Signal interface.
type Signal int

func (s Signal) Signal() {}

func (s Signal) String() string {
    // ... a few lines of code
}

It’s just an underlying int with a no-op Signal() method and the Stringer implementation.

So you can declare your own constants the same way for the signals you want to catch, by converting arbitrary int values:

const (
    SIGRTMIN = syscall.Signal(0x22)
)

signal.Notify(sigChan, SIGRTMIN, /* etc. */)

Answered By – blackgreen

Answer Checked By – Katrina (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.