Skip to content

proposal: context.WithSignal #21521

Closed
Closed
@markbates

Description

@markbates

A common design pattern when building applications is to trap signals, such as CTRL-C, and gracefully close down the application.

One might think this pattern is fairly straightforward and easy to implement. To illustrate the difficulties in getting this pattern correct, let's look at the following example.

In June, @matryer, wrote a blog post demonstrating how to capture signals in your application and use them to gracefully shutdown an application. This post resulted in a fantastic thread on Twitter with @Sajmani and @quentinmit pointing out the mistakes in Mat's code that demonstrate the subtleties in getting the implementation correct .

I propose that this type of cancellation, by signals, should be a part of the context package, as it follows the same idea as cancellation after a certain time, or by a deadline. Not only does this solve the problems with capturing signals that most people make, but, I believe, is another great use case for cancellation via contexts.

An example of this addition to the context package would work is as follows:

func main() {
	ctx, cancel := context.WithSignal(context.Background(), os.Interrupt)
	defer cancel()
	select {
	case <-ctx.Done():
		fmt.Println("thanks for stopping me")
	}
}

And a proposed implementation of the WithSignal function.

func WithSignal(ctx Context, s ...os.Signal) (Context, CancelFunc) {
	ctx, cancel := WithCancel(ctx)
	c := make(chan os.Signal, 1)
	signal.Notify(c, s...)
	go func() {
		select {
		case <-c:
			cancel()
		case <-ctx.Done():
			cancel()
		}
		signal.Stop(c)
	}()
	return ctx, cancel
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions