diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index b1d9d696ea3cb6c800343628f3cc854684617dc4..7ccaf8776d6460f36bb9fff15668ec87dc7fae69 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().ContextIsReadyToBeClosed) + if rootRedirect != nil { opts = append(opts, rootRedirect) } diff --git a/cmd/ipfs/main.go b/cmd/ipfs/main.go index 8dc1f9d0b40448e65499b2e223da4f054e214016..69050804ccd14df8da197bc363819a57c4a15956 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().ContextIsReadyToBeClosed) + } + // ok, finally, run the command invocation. output, err := invoc.Run(ctx) if err != nil { @@ -473,6 +481,9 @@ func (i *cmdInvocation) setupInterruptHandler() { sig := allInterruptSignals() go func() { + // wait till the context is ready to be closed + <-ctx.ContextIsReadyToBeClosed + // first time, try to shut down. // loop because we may be diff --git a/commands/request.go b/commands/request.go index c9748198b335cbef1bf2a3762dd97e37c6464b32..6a5e0577532c310033876805cf62cce15a03c85e 100644 --- a/commands/request.go +++ b/commands/request.go @@ -28,8 +28,9 @@ type Context struct { config *config.Config LoadConfig func(path string) (*config.Config, error) - node *core.IpfsNode - ConstructNode func() (*core.IpfsNode, error) + node *core.IpfsNode + ConstructNode func() (*core.IpfsNode, error) + ContextIsReadyToBeClosed 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(), ContextIsReadyToBeClosed: make(chan bool)} values := make(map[string]interface{}) req := &request{path, opts, args, file, cmd, ctx, optDefs, values, os.Stdin} err := req.ConvertOptions()