From afd497e194e8374b848a3ab2f91f8b820010035f Mon Sep 17 00:00:00 2001
From: Konstantin Koroviev <kkoroviev@gmail.com>
Date: Mon, 9 Mar 2015 15:43:10 +0200
Subject: [PATCH] Dirty hack to fix race conditions in the daemon

---
 cmd/ipfs/daemon.go  |  4 ++++
 cmd/ipfs/main.go    | 11 +++++++++++
 commands/request.go |  7 ++++---
 3 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go
index b1d9d696e..7ccaf8776 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 8dc1f9d0b..69050804c 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 c9748198b..6a5e05775 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()
-- 
GitLab