Merge pull request #1416 from mattn/fix-stmt-close-race
Fix race in SQLiteStmt.Close by holding conn lock across cache check
This commit is contained in:
32
sqlite3.go
32
sqlite3.go
@@ -445,12 +445,12 @@ type SQLiteDriver struct {
|
|||||||
|
|
||||||
// SQLiteConn implements driver.Conn.
|
// SQLiteConn implements driver.Conn.
|
||||||
type SQLiteConn struct {
|
type SQLiteConn struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
db *C.sqlite3
|
db *C.sqlite3
|
||||||
loc *time.Location
|
loc *time.Location
|
||||||
txlock string
|
txlock string
|
||||||
funcs []*functionInfo
|
funcs []*functionInfo
|
||||||
aggregators []*aggInfo
|
aggregators []*aggInfo
|
||||||
// Prepared-statement cache. The slice is allocated at Open with a
|
// Prepared-statement cache. The slice is allocated at Open with a
|
||||||
// fixed capacity equal to the configured cache size; cap bounds the
|
// fixed capacity equal to the configured cache size; cap bounds the
|
||||||
// cache, len is the live count, and entries are ordered LRU-first
|
// cache, len is the live count, and entries are ordered LRU-first
|
||||||
@@ -1970,6 +1970,10 @@ func (c *SQLiteConn) putCachedStmt(s *SQLiteStmt) bool {
|
|||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
return c.putCachedStmtLocked(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *SQLiteConn) putCachedStmtLocked(s *SQLiteStmt) bool {
|
||||||
if c.db == nil {
|
if c.db == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -2164,12 +2168,20 @@ func (s *SQLiteStmt) Close() error {
|
|||||||
s.c = nil
|
s.c = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if !conn.dbConnOpen() {
|
if s.cacheKey != "" {
|
||||||
|
conn.mu.Lock()
|
||||||
|
if conn.db == nil {
|
||||||
|
conn.mu.Unlock()
|
||||||
|
return errors.New("sqlite statement with already closed database connection")
|
||||||
|
}
|
||||||
|
if conn.putCachedStmtLocked(s) {
|
||||||
|
conn.mu.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
conn.mu.Unlock()
|
||||||
|
} else if !conn.dbConnOpen() {
|
||||||
return errors.New("sqlite statement with already closed database connection")
|
return errors.New("sqlite statement with already closed database connection")
|
||||||
}
|
}
|
||||||
if s.cacheKey != "" && conn.putCachedStmt(s) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s.s = nil
|
s.s = nil
|
||||||
s.c = nil
|
s.c = nil
|
||||||
rv := C.sqlite3_finalize(stmt)
|
rv := C.sqlite3_finalize(stmt)
|
||||||
|
|||||||
Reference in New Issue
Block a user