From 110be07f7892bd803b54a17a44328d91497bb059 Mon Sep 17 00:00:00 2001 From: Charlie Vieth Date: Sun, 8 Dec 2024 19:47:14 -0500 Subject: [PATCH] make sure Close always removes the runtime finalizer This commit fixes a bug in {SQLiteConn,SQLiteStmt}.Close that would lead to the runtime finalizer not being removed if there was an error closing the connection or statement. This commit also makes it safe to call SQLiteConn.Close multiple times. --- sqlite3.go | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/sqlite3.go b/sqlite3.go index ce985ec8..cead9921 100644 --- a/sqlite3.go +++ b/sqlite3.go @@ -1782,26 +1782,20 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) { } // Close the connection. -func (c *SQLiteConn) Close() error { +func (c *SQLiteConn) Close() (err error) { + c.mu.Lock() + defer c.mu.Unlock() + if c.db == nil { + return nil // Already closed + } + runtime.SetFinalizer(c, nil) rv := C.sqlite3_close_v2(c.db) if rv != C.SQLITE_OK { - return c.lastError() + err = c.lastError() } deleteHandles(c) - c.mu.Lock() c.db = nil - c.mu.Unlock() - runtime.SetFinalizer(c, nil) - return nil -} - -func (c *SQLiteConn) dbConnOpen() bool { - if c == nil { - return false - } - c.mu.Lock() - defer c.mu.Unlock() - return c.db != nil + return err } // Prepare the query string. Return a new statement. @@ -1901,16 +1895,15 @@ func (s *SQLiteStmt) Close() error { return nil } s.closed = true - if !s.c.dbConnOpen() { - return errors.New("sqlite statement with already closed database connection") - } - rv := C.sqlite3_finalize(s.s) + conn := s.c + stmt := s.s + s.c = nil s.s = nil + runtime.SetFinalizer(s, nil) + rv := C.sqlite3_finalize(stmt) if rv != C.SQLITE_OK { - return s.c.lastError() + return conn.lastError() } - s.c = nil - runtime.SetFinalizer(s, nil) return nil }