Skip to content

Commit 34e4bf7

Browse files
committed
🐛 Fix rare map race condition
When two connections are closed at the same time, the MySQL connection map might be read and written at the same time, resulting in a panic. Now, a mutex ensures no race condition can occur.
1 parent c823aac commit 34e4bf7

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

namespace/mysql_handler.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,15 @@ func (h *handler) NewConnection(c *mysql.Conn) {
115115

116116
func (h *handler) ConnectionClosed(c *mysql.Conn) {
117117
h.Logger.Info("Connection closed", "connectionID", c.ConnectionID, "username", c.User)
118-
118+
// You might be tempted to just have a top lock and just defer the unlock
119+
//
120+
// However, it's not working for some reasons when two connections are created at the same time
121+
// (probably related to a global database/sql variable because test clients and the test server are using sql.register)
122+
// Also, because conn.Close() can take some time, we don't want to block the other goroutines.
123+
h.mutexConnectionMapperSQLite.Lock()
119124
// Close the connection associated with the MySQL connection
120125
if conn, ok := h.connectionMapperSQLite[c.ConnectionID]; ok {
126+
h.mutexConnectionMapperSQLite.Unlock()
121127
// Return the connection to the pool
122128
err := conn.Close()
123129
if err != nil {
@@ -127,7 +133,9 @@ func (h *handler) ConnectionClosed(c *mysql.Conn) {
127133
h.mutexConnectionMapperSQLite.Lock()
128134
delete(h.connectionMapperSQLite, c.ConnectionID)
129135
h.mutexConnectionMapperSQLite.Unlock()
136+
130137
} else {
138+
h.mutexConnectionMapperSQLite.Unlock()
131139
h.Logger.Error("SQLite connection not found", "connectionID", c.ConnectionID, "username", c.User)
132140
}
133141

@@ -249,7 +257,9 @@ func (h *handler) runSimpleQuery(connectionID uint32, query string, args ...any)
249257
h.Logger.Debug("Running query: ", "query", query)
250258

251259
// Retrieve the connection associated with the MySQL connection
260+
h.mutexConnectionMapperSQLite.Lock() // To ensure we don't read during a write
252261
conn, ok := h.connectionMapperSQLite[connectionID]
262+
h.mutexConnectionMapperSQLite.Unlock()
253263
if !ok {
254264
h.Logger.Error("SQLite connection not found", "connectionID", connectionID)
255265
return nil, fmt.Errorf("SQLite connection not found")

0 commit comments

Comments
 (0)