-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathcontext.go
74 lines (61 loc) · 1.89 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package cli
import (
"context"
"os"
"os/signal"
"syscall"
"gopkg.in/src-d/go-log.v1"
)
// ContextCommander is a cancellable commander. By default, receiving SIGTERM or
// SIGINT will cancel the context. For overriding the default behaviour, see the
// SignalHandler interface.
type ContextCommander interface {
// ExecuteContext executes the command with a context.
ExecuteContext(context.Context, []string) error
}
// SignalHandler can be implemented by a ContextCommander to override default
// signal handling (which is logging the signal and cancelling the context).
// If this interface is implemented, HandleSignal will be called when SIGTERM or
// SIGINT is received, and no other signal handling will be performed.
type SignalHandler interface {
// HandleSignal takes the received signal (SIGTERM or SIGINT) and the
// CancelFunc of the context.Context passed to ExecuteContext.
HandleSignal(os.Signal, context.CancelFunc)
}
func executeContextCommander(cmd ContextCommander, args []string) error {
handler := defaultSignalHandler
if v, ok := cmd.(SignalHandler); ok {
handler = v.HandleSignal
}
ctx := setupContext(handler)
return cmd.ExecuteContext(ctx, args)
}
func defaultSignalHandler(signal os.Signal, cancel context.CancelFunc) {
switch signal {
case syscall.SIGTERM:
log.Infof("signal SIGTERM received, stopping...")
case os.Interrupt:
log.Infof("signal SIGINT received, stopping...")
}
cancel()
}
func setupContext(handler func(os.Signal, context.CancelFunc)) context.Context {
var (
sigterm = make(chan os.Signal)
sigint = make(chan os.Signal)
)
ctx, cancel := context.WithCancel(context.Background())
go func() {
select {
case sig := <-sigterm:
handler(sig, cancel)
case sig := <-sigint:
handler(sig, cancel)
}
signal.Stop(sigterm)
signal.Stop(sigint)
}()
signal.Notify(sigterm, syscall.SIGTERM)
signal.Notify(sigint, os.Interrupt)
return ctx
}