main: move InterruptHandler to util
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Dec 23, 2018 at 18:11 UTC
435a3da07ff4448ec41b9d0927013ba51a8b473f
3 files changed
+97
-69
cmd/ipfs/main.go
+2
-69
@@ -5,17 +5,14 @@ import (
5
"context"
6
"errors"
7
"fmt"
8
- "io"
8
"math/rand"
9
"os"
11
- "os/signal"
10
"path/filepath"
11
"runtime/pprof"
12
"strings"
15
- "sync"
16
- "syscall"
13
"time"
14
15
+ util "github.com/ipfs/go-ipfs/cmd/ipfs/util"
16
oldcmds "github.com/ipfs/go-ipfs/commands"
17
core "github.com/ipfs/go-ipfs/core"
18
corecmds "github.com/ipfs/go-ipfs/core/commands"
@@ -106,7 +103,7 @@ func mainRet() int {
103
}
104
defer stopFunc() // to be executed as late as possible
105
109
- intrh, ctx := setupInterruptHandler(ctx)
106
+ intrh, ctx := util.SetupInterruptHandler(ctx)
107
defer intrh.Close()
108
109
// Handle `ipfs version` or `ipfs help`
@@ -355,70 +352,6 @@ func writeHeapProfileToFile() error {
352
return pprof.WriteHeapProfile(mprof)
353
}
354
358
-// IntrHandler helps set up an interrupt handler that can
359
-// be cleanly shut down through the io.Closer interface.
360
-type IntrHandler struct {
361
- sig chan os.Signal
362
- wg sync.WaitGroup
363
-}
364
-
365
-func NewIntrHandler() *IntrHandler {
366
- ih := &IntrHandler{}
367
- ih.sig = make(chan os.Signal, 1)
368
- return ih
369
-}
370
-
371
-func (ih *IntrHandler) Close() error {
372
- close(ih.sig)
373
- ih.wg.Wait()
374
- return nil
375
-}
376
-
377
-// Handle starts handling the given signals, and will call the handler
378
-// callback function each time a signal is catched. The function is passed
379
-// the number of times the handler has been triggered in total, as
380
-// well as the handler itself, so that the handling logic can use the
381
-// handler's wait group to ensure clean shutdown when Close() is called.
382
-func (ih *IntrHandler) Handle(handler func(count int, ih *IntrHandler), sigs ...os.Signal) {
383
- signal.Notify(ih.sig, sigs...)
384
- ih.wg.Add(1)
385
- go func() {
386
- defer ih.wg.Done()
387
- count := 0
388
- for range ih.sig {
389
- count++
390
- handler(count, ih)
391
- }
392
- signal.Stop(ih.sig)
393
- }()
394
-}
395
-
396
-func setupInterruptHandler(ctx context.Context) (io.Closer, context.Context) {
397
- intrh := NewIntrHandler()
398
- ctx, cancelFunc := context.WithCancel(ctx)
399
-
400
- handlerFunc := func(count int, ih *IntrHandler) {
401
- switch count {
402
- case 1:
403
- fmt.Println() // Prevent un-terminated ^C character in terminal
404
-
405
- ih.wg.Add(1)
406
- go func() {
407
- defer ih.wg.Done()
408
- cancelFunc()
409
- }()
410
-
411
- default:
412
- fmt.Println("Received another interrupt before graceful shutdown, terminating...")
413
- os.Exit(-1)
414
- }
415
- }
416
-
417
- intrh.Handle(handlerFunc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
418
-
419
- return intrh, ctx
420
-}
421
-
355
func profileIfEnabled() (func(), error) {
356
// FIXME this is a temporary hack so profiling of asynchronous operations
357
// works as intended.
cmd/ipfs/util/signal.go
new
+77
@@ -0,0 +1,77 @@
1
+// +build !wasm
2
+
3
+package util
4
+
5
+import (
6
+ "context"
7
+ "fmt"
8
+ "io"
9
+ "os"
10
+ "os/signal"
11
+ "sync"
12
+ "syscall"
13
+)
14
+
15
+// IntrHandler helps set up an interrupt handler that can
16
+// be cleanly shut down through the io.Closer interface.
17
+type IntrHandler struct {
18
+ sig chan os.Signal
19
+ wg sync.WaitGroup
20
+}
21
+
22
+func NewIntrHandler() *IntrHandler {
23
+ ih := &IntrHandler{}
24
+ ih.sig = make(chan os.Signal, 1)
25
+ return ih
26
+}
27
+
28
+func (ih *IntrHandler) Close() error {
29
+ close(ih.sig)
30
+ ih.wg.Wait()
31
+ return nil
32
+}
33
+
34
+// Handle starts handling the given signals, and will call the handler
35
+// callback function each time a signal is catched. The function is passed
36
+// the number of times the handler has been triggered in total, as
37
+// well as the handler itself, so that the handling logic can use the
38
+// handler's wait group to ensure clean shutdown when Close() is called.
39
+func (ih *IntrHandler) Handle(handler func(count int, ih *IntrHandler), sigs ...os.Signal) {
40
+ signal.Notify(ih.sig, sigs...)
41
+ ih.wg.Add(1)
42
+ go func() {
43
+ defer ih.wg.Done()
44
+ count := 0
45
+ for range ih.sig {
46
+ count++
47
+ handler(count, ih)
48
+ }
49
+ signal.Stop(ih.sig)
50
+ }()
51
+}
52
+
53
+func SetupInterruptHandler(ctx context.Context) (io.Closer, context.Context) {
54
+ intrh := NewIntrHandler()
55
+ ctx, cancelFunc := context.WithCancel(ctx)
56
+
57
+ handlerFunc := func(count int, ih *IntrHandler) {
58
+ switch count {
59
+ case 1:
60
+ fmt.Println() // Prevent un-terminated ^C character in terminal
61
+
62
+ ih.wg.Add(1)
63
+ go func() {
64
+ defer ih.wg.Done()
65
+ cancelFunc()
66
+ }()
67
+
68
+ default:
69
+ fmt.Println("Received another interrupt before graceful shutdown, terminating...")
70
+ os.Exit(-1)
71
+ }
72
+ }
73
+
74
+ intrh.Handle(handlerFunc, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)
75
+
76
+ return intrh, ctx
77
+}
cmd/ipfs/util/signal_wasm.go
new
+18
@@ -0,0 +1,18 @@
1
+package util
2
+
3
+import (
4
+ "context"
5
+ "io"
6
+)
7
+
8
+type ctxCloser context.CancelFunc
9
+
10
+func (c ctxCloser) Close() error {
11
+ c()
12
+ return nil
13
+}
14
+
15
+func SetupInterruptHandler(ctx context.Context) (io.Closer, context.Context) {
16
+ ctx, cancel := context.WithCancel(ctx)
17
+ return ctxCloser(cancel), ctx
18
+}