Skip to content

Commit 7f02e6b

Browse files
authored
Merge pull request lib#1035 from bjornouderoelink/fix-concurrent-map-writes
Fix lib#1031: concurrent map writes
2 parents b2901c7 + 69b14f1 commit 7f02e6b

File tree

3 files changed

+19
-12
lines changed

3 files changed

+19
-12
lines changed

conn.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,13 @@ func (c *Connector) open(ctx context.Context) (cn *conn, err error) {
298298
// the user.
299299
defer errRecoverNoErrBadConn(&err)
300300

301-
o := c.opts
301+
// Create a new values map (copy). This makes it so maps in different
302+
// connections do not reference the same underlying data structure, so it
303+
// is safe for multiple connections to concurrently write to their opts.
304+
o := make(values)
305+
for k, v := range c.opts {
306+
o[k] = v
307+
}
302308

303309
bad := &atomic.Value{}
304310
bad.Store(false)
@@ -1100,7 +1106,7 @@ func isDriverSetting(key string) bool {
11001106
return true
11011107
case "password":
11021108
return true
1103-
case "sslmode", "sslcert", "sslkey", "sslrootcert":
1109+
case "sslmode", "sslcert", "sslkey", "sslrootcert", "sslinline":
11041110
return true
11051111
case "fallback_application_name":
11061112
return true

conn_go18.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,16 @@ func (cn *conn) watchCancel(ctx context.Context) func() {
129129
}
130130

131131
func (cn *conn) cancel(ctx context.Context) error {
132-
c, err := dial(ctx, cn.dialer, cn.opts)
132+
// Create a new values map (copy). This makes sure the connection created
133+
// in this method cannot write to the same underlying data, which could
134+
// cause a concurrent map write panic. This is necessary because cancel
135+
// is called from a goroutine in watchCancel.
136+
o := make(values)
137+
for k, v := range cn.opts {
138+
o[k] = v
139+
}
140+
141+
c, err := dial(ctx, cn.dialer, o)
133142
if err != nil {
134143
return err
135144
}
@@ -142,7 +151,7 @@ func (cn *conn) cancel(ctx context.Context) error {
142151
c: c,
143152
bad: bad,
144153
}
145-
err = can.ssl(cn.opts)
154+
err = can.ssl(o)
146155
if err != nil {
147156
return err
148157
}

ssl.go

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ func ssl(o values) (func(net.Conn) (net.Conn, error), error) {
5959
return nil, err
6060
}
6161

62-
// This pseudo-parameter is not recognized by the PostgreSQL server, so let's delete it after use.
63-
delete(o, "sslinline")
64-
6562
// Accept renegotiation requests initiated by the backend.
6663
//
6764
// Renegotiation was deprecated then removed from PostgreSQL 9.5, but
@@ -89,9 +86,6 @@ func sslClientCertificates(tlsConf *tls.Config, o values) error {
8986
sslinline := o["sslinline"]
9087
if sslinline == "true" {
9188
cert, err := tls.X509KeyPair([]byte(o["sslcert"]), []byte(o["sslkey"]))
92-
// Clear out these params, in case they were to be sent to the PostgreSQL server by mistake
93-
o["sslcert"] = ""
94-
o["sslkey"] = ""
9589
if err != nil {
9690
return err
9791
}
@@ -157,8 +151,6 @@ func sslCertificateAuthority(tlsConf *tls.Config, o values) error {
157151

158152
var cert []byte
159153
if sslinline == "true" {
160-
// // Clear out this param, in case it were to be sent to the PostgreSQL server by mistake
161-
o["sslrootcert"] = ""
162154
cert = []byte(sslrootcert)
163155
} else {
164156
var err error

0 commit comments

Comments
 (0)