Skip to content

Commit d076090

Browse files
Fix concurrent map writes.
This commit should fix an issue with concurrent map writes by making the opts values map in separate connections not reference the same underlying data.
1 parent b2901c7 commit d076090

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

conn.go

Lines changed: 7 additions & 1 deletion
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)

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
}

0 commit comments

Comments
 (0)