go: proposal: os/signal: Provide a new error type to communicate the signal triggered context cancellation

This comes from the need to fix #60733.

In order to provide the information of which signal triggered context cancellation in signal.NotifyContext using context.Cause, we need a new error type (as that’s the only type allowed by context cause) to communicate that info back to the user.

The proposal is to define it as a simple struct that can only be used by pointer as an error:

// CanceledBySignalError represents the error can be retrieved via context.Cause
// on the context returned by NotifyContext to inspect which signal caused the
// cancellation.
type CanceledBySignalError struct {
	// The signal caused the context cancellation.
	Signal os.Signal
}

func (cse *CanceledBySignalError) Error() string {
	return fmt.Sprintf("context canceled by signal %v", cse.Signal)
}

So users can inspect the signal via code like:

select {
case <-ctx.Done():
  cause := context.Cause(ctx)
  var cse *signal.CanceledBySignalError
  if errors.As(cause, &cse) {
    sig := cse.Signal
    // Do something with sig
  }
}

About this issue

  • Original URL
  • State: open
  • Created a year ago
  • Reactions: 8
  • Comments: 15 (7 by maintainers)

Most upvoted comments

I think this should be named os.SignalError instead of signal.CanceledBySignalError, so that it may be used for cases beyond just signal.Notify. For example, I could envision a caller transforming an exec.ExitError by checking whether its ProcessState indicates termination by signal and returning a SignalError.

Actually, SignalError would be even more useful if exec.ExitError had a convenience Is method for it:

	err := cmd.Wait()
	if errors.Is(err, os.SignalError{Signal: syscall.SIGABRT}) {
		// err indicates termination due to signal SIGABRT — program probably failed an assertion
		…
	}