@cryptotaxi247 / kubo / commits / 705465db8

main + daemon signal handlers

This commit changes the signal handler to be added once the command is executing. this is because the daemon has its own signal handler, that must try to shut down the node gracefully first. You know, just in case.

Juan Batiz-Benet committed Nov 16, 2014 at 02:11 UTC 705465db8bd11627762c9e6bf09c49d098770f1e
2 files changed +42 -24
cmd/ipfs2/daemon.go
+10 -18
@@ -3,9 +3,6 @@ package main
3 import (
4 "fmt"
5 "net/http"
6 - "os"
7 - "os/signal"
8 - "syscall"
6
7 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8 manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
@@ -74,40 +71,35 @@ func daemonFunc(req cmds.Request) (interface{}, error) {
71 ifpsHandler := &ipfsHandler{node}
72 mux.Handle("/ipfs/", ifpsHandler)
73
77 - err = listenAndServe(mux, host)
74 + err = listenAndServe(node, mux, host)
75 return nil, err
76 }
77
81 -func listenAndServe(mux *http.ServeMux, host string) error {
78 +func listenAndServe(node *core.IpfsNode, mux *http.ServeMux, host string) error {
79
80 fmt.Printf("API server listening on '%s'\n", host)
81 s := manners.NewServer()
82 +
83 done := make(chan struct{}, 1)
84 defer func() {
85 done <- struct{}{}
86 }()
87
90 - // go wait until we kill it.
88 + // go wait until the node dies
89 go func() {
92 - sig := sigTerm()
90 select {
91 + case <-node.Closed():
92 case <-done:
95 - log.Info("daemon terminated at %s.", host)
96 - case <-sig:
97 - s.Shutdown <- true
98 - log.Info("terminating daemon at %s...", host)
93 + return
94 }
95 +
96 + log.Info("terminating daemon at %s...", host)
97 + s.Shutdown <- true
98 }()
99
100 if err := s.ListenAndServe(host, mux); err != nil {
101 return err
102 }
105 - return nil
106 -}
103
108 -func sigTerm() chan os.Signal {
109 - sigc := make(chan os.Signal, 1)
110 - signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
111 - syscall.SIGTERM, syscall.SIGQUIT)
112 - return sigc
104 + return nil
105 }
cmd/ipfs2/main.go
+32 -6
@@ -7,6 +7,7 @@ import (
7 "os"
8 "os/signal"
9 "runtime/pprof"
10 + "syscall"
11
12 logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
13 ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
@@ -124,7 +125,8 @@ func main() {
125 }
126
127 func (i *cmdInvocation) Run() (output io.Reader, err error) {
127 - handleInterrupt()
128 + // setup our global interrupt handler.
129 + i.setupInterruptHandler()
130
131 // check if user wants to debug. option OR env var.
132 debug, _, err := i.req.Option("debug").Bool()
@@ -281,6 +283,7 @@ func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
283 // this sets up the function that will initialize the node
284 // this is so that we can construct the node lazily.
285 ctx := req.Context()
286 +
287 ctx.ConstructNode = func() (*core.IpfsNode, error) {
288 cfg, err := ctx.GetConfig()
289 if err != nil {
@@ -442,14 +445,37 @@ func writeHeapProfileToFile() error {
445 }
446
447 // listen for and handle SIGTERM
445 -func handleInterrupt() {
446 - c := make(chan os.Signal, 1)
447 - signal.Notify(c, os.Interrupt)
448 +func (i *cmdInvocation) setupInterruptHandler() {
449 +
450 + ctx := i.req.Context()
451 + sig := allInterruptSignals()
452
453 go func() {
450 - for _ = range c {
451 - log.Info("Received interrupt signal, terminating...")
454 +
455 + for {
456 + // first time, try to shut down.
457 + <-sig
458 + log.Critical("Received interrupt signal, shutting down...")
459 +
460 + n, err := ctx.GetNode()
461 + if err == nil {
462 + go n.Close()
463 + select {
464 + case <-n.Closed():
465 + case <-sig:
466 + log.Critical("Received another interrupt signal, terminating...")
467 + }
468 + }
469 +
470 os.Exit(0)
471 }
472 +
473 }()
474 }
475 +
476 +func allInterruptSignals() chan os.Signal {
477 + sigc := make(chan os.Signal, 1)
478 + signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
479 + syscall.SIGTERM, syscall.SIGQUIT)
480 + return sigc
481 +}