diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index b1d9d696e..e8794f68a 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -267,6 +267,10 @@ func daemonFunc(req cmds.Request, res cmds.Response) { gateway.ServeOption(), corehttp.VersionOption(), } + + // our global interrupt handler can now try to stop the daemon + close(req.Context().InitDone) + if rootRedirect != nil { opts = append(opts, rootRedirect) } diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 8dc1f9d0b..2bca9dd45 100644 --- a/cmd/ipfs/main.go +++ b/cmd/ipfs/main.go @@ -132,6 +132,14 @@ func main() { os.Exit(1) } + // our global interrupt handler may try to stop the daemon + // before the daemon is ready to be stopped; this dirty + // workaround is for the daemon only; other commands are always + // ready to be stopped + if invoc.cmd != daemonCmd { + close(invoc.req.Context().InitDone) + } + // ok, finally, run the command invocation. output, err := invoc.Run(ctx) if err != nil { @@ -479,6 +487,14 @@ func (i *cmdInvocation) setupInterruptHandler() { for count := 0; ; count++ { <-sig + // if we're still initializing, cannot use `ctx.GetNode()` + select { + default: // initialization not done + fmt.Println("Received interrupt signal, shutting down...") + os.Exit(-1) + case <-ctx.InitDone: + } + // TODO cancel the command context instead n, err := ctx.GetNode() diff --git a/commands/request.go b/commands/request.go index c9748198b..e7f9d4e33 100644 --- a/commands/request.go +++ b/commands/request.go @@ -30,6 +30,7 @@ type Context struct { node *core.IpfsNode ConstructNode func() (*core.IpfsNode, error) + InitDone chan bool } // GetConfig returns the config of the current Command exection @@ -287,7 +288,7 @@ func NewRequest(path []string, opts OptMap, args []string, file files.File, cmd optDefs = make(map[string]Option) } - ctx := Context{Context: context.TODO()} + ctx := Context{Context: context.TODO(), InitDone: make(chan bool)} values := make(map[string]interface{}) req := &request{path, opts, args, file, cmd, ctx, optDefs, values, os.Stdin} err := req.ConvertOptions()