|
1 | 1 | package signals
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "context" |
4 | 5 | "os"
|
5 | 6 | "os/signal"
|
| 7 | + "sync" |
6 | 8 | "syscall"
|
7 | 9 | )
|
8 | 10 |
|
9 |
| -var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} |
10 |
| -var onlyOneSignalHandler = make(chan struct{}) |
| 11 | +var ( |
| 12 | + shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} |
| 13 | + signalCtx context.Context |
| 14 | + cancel context.CancelFunc |
| 15 | + once sync.Once |
| 16 | +) |
11 | 17 |
|
12 |
| -// SetupSignalHandler registered for SIGTERM and SIGINT. A stop channel is returned |
13 |
| -// which is closed on one of these signals. If a second signal is caught, the program |
14 |
| -// is terminated with exit code 1. |
15 |
| -func SetupSignalHandler() (stopCh <-chan struct{}) { |
16 |
| - close(onlyOneSignalHandler) // panics when called twice |
| 18 | +// Context returns a Context registered to close on SIGTERM and SIGINT. |
| 19 | +// If a second signal is caught, the program is terminated with exit code 1. |
| 20 | +func Context() context.Context { |
| 21 | + once.Do(func() { |
| 22 | + c := make(chan os.Signal, 2) |
| 23 | + signal.Notify(c, shutdownSignals...) |
| 24 | + signalCtx, cancel = context.WithCancel(context.Background()) |
| 25 | + go func() { |
| 26 | + <-c |
| 27 | + cancel() |
17 | 28 |
|
18 |
| - stop := make(chan struct{}) |
19 |
| - c := make(chan os.Signal, 2) |
20 |
| - signal.Notify(c, shutdownSignals...) |
21 |
| - go func() { |
22 |
| - <-c |
23 |
| - close(stop) |
24 |
| - <-c |
25 |
| - os.Exit(1) // second signal. Exit directly. |
26 |
| - }() |
| 29 | + select { |
| 30 | + case <-signalCtx.Done(): |
| 31 | + case <-c: |
| 32 | + os.Exit(1) // second signal. Exit directly. |
| 33 | + } |
| 34 | + }() |
| 35 | + }) |
27 | 36 |
|
28 |
| - return stop |
| 37 | + return signalCtx |
29 | 38 | }
|
0 commit comments