提交 705465db 作者: Juan Batiz-Benet

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.
上级 6ff472be
......@@ -3,9 +3,6 @@ package main
import (
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
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) {
ifpsHandler := &ipfsHandler{node}
mux.Handle("/ipfs/", ifpsHandler)
err = listenAndServe(mux, host)
err = listenAndServe(node, mux, host)
return nil, err
}
func listenAndServe(mux *http.ServeMux, host string) error {
func listenAndServe(node *core.IpfsNode, mux *http.ServeMux, host string) error {
fmt.Printf("API server listening on '%s'\n", host)
s := manners.NewServer()
done := make(chan struct{}, 1)
defer func() {
done <- struct{}{}
}()
// go wait until we kill it.
// go wait until the node dies
go func() {
sig := sigTerm()
select {
case <-node.Closed():
case <-done:
log.Info("daemon terminated at %s.", host)
case <-sig:
s.Shutdown <- true
log.Info("terminating daemon at %s...", host)
return
}
log.Info("terminating daemon at %s...", host)
s.Shutdown <- true
}()
if err := s.ListenAndServe(host, mux); err != nil {
return err
}
return nil
}
func sigTerm() chan os.Signal {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
syscall.SIGTERM, syscall.SIGQUIT)
return sigc
return nil
}
......@@ -7,6 +7,7 @@ import (
"os"
"os/signal"
"runtime/pprof"
"syscall"
logging "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-logging"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
......@@ -124,7 +125,8 @@ func main() {
}
func (i *cmdInvocation) Run() (output io.Reader, err error) {
handleInterrupt()
// setup our global interrupt handler.
i.setupInterruptHandler()
// check if user wants to debug. option OR env var.
debug, _, err := i.req.Option("debug").Bool()
......@@ -281,6 +283,7 @@ func callCommand(req cmds.Request, root *cmds.Command) (cmds.Response, error) {
// this sets up the function that will initialize the node
// this is so that we can construct the node lazily.
ctx := req.Context()
ctx.ConstructNode = func() (*core.IpfsNode, error) {
cfg, err := ctx.GetConfig()
if err != nil {
......@@ -442,14 +445,37 @@ func writeHeapProfileToFile() error {
}
// listen for and handle SIGTERM
func handleInterrupt() {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
func (i *cmdInvocation) setupInterruptHandler() {
ctx := i.req.Context()
sig := allInterruptSignals()
go func() {
for _ = range c {
log.Info("Received interrupt signal, terminating...")
for {
// first time, try to shut down.
<-sig
log.Critical("Received interrupt signal, shutting down...")
n, err := ctx.GetNode()
if err == nil {
go n.Close()
select {
case <-n.Closed():
case <-sig:
log.Critical("Received another interrupt signal, terminating...")
}
}
os.Exit(0)
}
}()
}
func allInterruptSignals() chan os.Signal {
sigc := make(chan os.Signal, 1)
signal.Notify(sigc, syscall.SIGHUP, syscall.SIGINT,
syscall.SIGTERM, syscall.SIGQUIT)
return sigc
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论