@cryptotaxi247 / kubo / commits / 435a3da07

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 +}