Browse code

re-vendor syslog log driver

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2016/11/22 04:24:53
Showing 3 changed files
... ...
@@ -19,7 +19,7 @@ golang.org/x/sys 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9
19 19
 github.com/docker/go-units 8a7beacffa3009a9ac66bad506b18ffdd110cf97
20 20
 github.com/docker/go-connections f512407a188ecb16f31a33dbc9c4e4814afc1b03
21 21
 
22
-github.com/RackSec/srslog 365bf33cd9acc21ae1c355209865f17228ca534e
22
+github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5
23 23
 github.com/imdario/mergo 0.2.1
24 24
 
25 25
 #get libnetwork packages
... ...
@@ -77,10 +77,7 @@ func DialWithTLSConfig(network, raddr string, priority Priority, tag string, tls
77 77
 		tlsConfig: tlsConfig,
78 78
 	}
79 79
 
80
-	w.Lock()
81
-	defer w.Unlock()
82
-
83
-	err := w.connect()
80
+	_, err := w.connect()
84 81
 	if err != nil {
85 82
 		return nil, err
86 83
 	}
... ...
@@ -8,8 +8,6 @@ import (
8 8
 
9 9
 // A Writer is a connection to a syslog server.
10 10
 type Writer struct {
11
-	sync.Mutex // guards conn
12
-
13 11
 	priority  Priority
14 12
 	tag       string
15 13
 	hostname  string
... ...
@@ -19,28 +17,48 @@ type Writer struct {
19 19
 	framer    Framer
20 20
 	formatter Formatter
21 21
 
22
+	mu   sync.RWMutex // guards conn
22 23
 	conn serverConn
23 24
 }
24 25
 
26
+// getConn provides access to the internal conn, protected by a mutex. The
27
+// conn is threadsafe, so it can be used while unlocked, but we want to avoid
28
+// race conditions on grabbing a reference to it.
29
+func (w *Writer) getConn() serverConn {
30
+	w.mu.RLock()
31
+	conn := w.conn
32
+	w.mu.RUnlock()
33
+	return conn
34
+}
35
+
36
+// setConn updates the internal conn, protected by a mutex.
37
+func (w *Writer) setConn(c serverConn) {
38
+	w.mu.Lock()
39
+	w.conn = c
40
+	w.mu.Unlock()
41
+}
42
+
25 43
 // connect makes a connection to the syslog server.
26
-// It must be called with w.mu held.
27
-func (w *Writer) connect() (err error) {
28
-	if w.conn != nil {
44
+func (w *Writer) connect() (serverConn, error) {
45
+	conn := w.getConn()
46
+	if conn != nil {
29 47
 		// ignore err from close, it makes sense to continue anyway
30
-		w.conn.close()
31
-		w.conn = nil
48
+		conn.close()
49
+		w.setConn(nil)
32 50
 	}
33 51
 
34
-	var conn serverConn
35 52
 	var hostname string
53
+	var err error
36 54
 	dialer := w.getDialer()
37 55
 	conn, hostname, err = dialer.Call()
38 56
 	if err == nil {
39
-		w.conn = conn
57
+		w.setConn(conn)
40 58
 		w.hostname = hostname
41
-	}
42 59
 
43
-	return
60
+		return conn, nil
61
+	} else {
62
+		return nil, err
63
+	}
44 64
 }
45 65
 
46 66
 // SetFormatter changes the formatter function for subsequent messages.
... ...
@@ -59,14 +77,17 @@ func (w *Writer) Write(b []byte) (int, error) {
59 59
 	return w.writeAndRetry(w.priority, string(b))
60 60
 }
61 61
 
62
+// WriteWithPriority sends a log message with a custom priority
63
+func (w *Writer) WriteWithPriority(p Priority, b []byte) (int, error) {
64
+	return w.writeAndRetry(p, string(b))
65
+}
66
+
62 67
 // Close closes a connection to the syslog daemon.
63 68
 func (w *Writer) Close() error {
64
-	w.Lock()
65
-	defer w.Unlock()
66
-
67
-	if w.conn != nil {
68
-		err := w.conn.close()
69
-		w.conn = nil
69
+	conn := w.getConn()
70
+	if conn != nil {
71
+		err := conn.close()
72
+		w.setConn(nil)
70 73
 		return err
71 74
 	}
72 75
 	return nil
... ...
@@ -131,29 +152,29 @@ func (w *Writer) Debug(m string) (err error) {
131 131
 func (w *Writer) writeAndRetry(p Priority, s string) (int, error) {
132 132
 	pr := (w.priority & facilityMask) | (p & severityMask)
133 133
 
134
-	w.Lock()
135
-	defer w.Unlock()
136
-
137
-	if w.conn != nil {
138
-		if n, err := w.write(pr, s); err == nil {
134
+	conn := w.getConn()
135
+	if conn != nil {
136
+		if n, err := w.write(conn, pr, s); err == nil {
139 137
 			return n, err
140 138
 		}
141 139
 	}
142
-	if err := w.connect(); err != nil {
140
+
141
+	var err error
142
+	if conn, err = w.connect(); err != nil {
143 143
 		return 0, err
144 144
 	}
145
-	return w.write(pr, s)
145
+	return w.write(conn, pr, s)
146 146
 }
147 147
 
148 148
 // write generates and writes a syslog formatted string. It formats the
149 149
 // message based on the current Formatter and Framer.
150
-func (w *Writer) write(p Priority, msg string) (int, error) {
150
+func (w *Writer) write(conn serverConn, p Priority, msg string) (int, error) {
151 151
 	// ensure it ends in a \n
152 152
 	if !strings.HasSuffix(msg, "\n") {
153 153
 		msg += "\n"
154 154
 	}
155 155
 
156
-	err := w.conn.writeString(w.framer, w.formatter, p, w.hostname, w.tag, msg)
156
+	err := conn.writeString(w.framer, w.formatter, p, w.hostname, w.tag, msg)
157 157
 	if err != nil {
158 158
 		return 0, err
159 159
 	}