Browse code

Call the Shutdown on the server

This is the right way to call for a clean shutdown

Return application/json as content-type when appropriate

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>

Flavio Crisciani authored on 2017/12/06 02:19:17
Showing 2 changed files
... ...
@@ -1306,19 +1306,19 @@ func (c *controller) Stop() {
1306 1306
 // StartDiagnose start the network diagnose mode
1307 1307
 func (c *controller) StartDiagnose(port int) {
1308 1308
 	c.Lock()
1309
-	defer c.Unlock()
1310 1309
 	if !c.DiagnoseServer.IsDebugEnable() {
1311 1310
 		c.DiagnoseServer.EnableDebug("127.0.0.1", port)
1312 1311
 	}
1312
+	c.Unlock()
1313 1313
 }
1314 1314
 
1315 1315
 // StopDiagnose start the network diagnose mode
1316 1316
 func (c *controller) StopDiagnose() {
1317 1317
 	c.Lock()
1318
-	defer c.Unlock()
1319 1318
 	if c.DiagnoseServer.IsDebugEnable() {
1320 1319
 		c.DiagnoseServer.DisableDebug()
1321 1320
 	}
1321
+	c.Unlock()
1322 1322
 }
1323 1323
 
1324 1324
 // IsDiagnoseEnabled returns true if the diagnose is enabled
... ...
@@ -1,12 +1,12 @@
1 1
 package diagnose
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"encoding/json"
5 6
 	"fmt"
6
-	"log"
7
-	"net"
8 7
 	"net/http"
9 8
 	"sync"
9
+	"sync/atomic"
10 10
 
11 11
 	stackdump "github.com/docker/docker/pkg/signal"
12 12
 	"github.com/docker/libnetwork/common"
... ...
@@ -36,7 +36,8 @@ var diagPaths2Func = map[string]HTTPHandlerFunc{
36 36
 // Server when the debug is enabled exposes a
37 37
 // This data structure is protected by the Agent mutex so does not require and additional mutex here
38 38
 type Server struct {
39
-	sk                net.Listener
39
+	enable            int32
40
+	srv               *http.Server
40 41
 	port              int
41 42
 	mux               *http.ServeMux
42 43
 	registeredHanders map[string]bool
... ...
@@ -71,6 +72,10 @@ func (n *Server) RegisterHandler(ctx interface{}, hdlrs map[string]HTTPHandlerFu
71 71
 	}
72 72
 }
73 73
 
74
+func (n *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
75
+	n.mux.ServeHTTP(w, r)
76
+}
77
+
74 78
 // EnableDebug opens a TCP socket to debug the passed network DB
75 79
 func (n *Server) EnableDebug(ip string, port int) {
76 80
 	n.Lock()
... ...
@@ -78,37 +83,41 @@ func (n *Server) EnableDebug(ip string, port int) {
78 78
 
79 79
 	n.port = port
80 80
 
81
-	if n.sk != nil {
81
+	if n.enable == 1 {
82 82
 		logrus.Info("The server is already up and running")
83 83
 		return
84 84
 	}
85 85
 
86
-	logrus.Infof("Starting the server listening on %d for commands", port)
87
-	// Create the socket
88
-	var err error
89
-	n.sk, err = net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))
90
-	if err != nil {
91
-		log.Fatal(err)
92
-	}
86
+	logrus.Infof("Starting the diagnose server listening on %d for commands", port)
87
+	srv := &http.Server{Addr: fmt.Sprintf("127.0.0.1:%d", port), Handler: n}
88
+	n.srv = srv
89
+	n.enable = 1
90
+	go func(n *Server) {
91
+		// Ingore ErrServerClosed that is returned on the Shutdown call
92
+		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
93
+			logrus.Errorf("ListenAndServe error: %s", err)
94
+			atomic.SwapInt32(&n.enable, 0)
95
+		}
96
+	}(n)
93 97
 
94
-	go func() {
95
-		http.Serve(n.sk, n.mux)
96
-	}()
97 98
 }
98 99
 
99 100
 // DisableDebug stop the dubug and closes the tcp socket
100 101
 func (n *Server) DisableDebug() {
101 102
 	n.Lock()
102 103
 	defer n.Unlock()
103
-	n.sk.Close()
104
-	n.sk = nil
104
+
105
+	n.srv.Shutdown(context.Background())
106
+	n.srv = nil
107
+	n.enable = 0
108
+	logrus.Info("Disabling the diagnose server")
105 109
 }
106 110
 
107 111
 // IsDebugEnable returns true when the debug is enabled
108 112
 func (n *Server) IsDebugEnable() bool {
109 113
 	n.Lock()
110 114
 	defer n.Unlock()
111
-	return n.sk != nil
115
+	return n.enable == 1
112 116
 }
113 117
 
114 118
 func notImplemented(ctx interface{}, w http.ResponseWriter, r *http.Request) {
... ...
@@ -197,6 +206,7 @@ func ParseHTTPFormOptions(r *http.Request) (bool, *JSONOutput) {
197 197
 func HTTPReply(w http.ResponseWriter, r *HTTPResult, j *JSONOutput) (int, error) {
198 198
 	var response []byte
199 199
 	if j.enable {
200
+		w.Header().Set("Content-Type", "application/json")
200 201
 		var err error
201 202
 		if j.prettyPrint {
202 203
 			response, err = json.MarshalIndent(r, "", "  ")