@@ -141,14 +141,18 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self,
141141}
142142
143143static inline int
144- stmt_reset (pysqlite_Statement * self )
144+ stmt_reset (pysqlite_Statement * self , int keep_in_use )
145145{
146146 int rc = SQLITE_OK ;
147147
148148 if (self -> st != NULL ) {
149149 Py_BEGIN_ALLOW_THREADS
150150 rc = sqlite3_reset (self -> st );
151151 Py_END_ALLOW_THREADS
152+
153+ if (rc == SQLITE_OK && !keep_in_use ) {
154+ pysqlite_statement_mark_in_use (self , 0 );
155+ }
152156 }
153157
154158 return rc ;
@@ -179,7 +183,7 @@ cursor_clear(PyObject *op)
179183 pysqlite_set_ref (op , & self -> row_factory , NULL );
180184 if (self -> statement ) {
181185 /* Reset the statement if the user has not closed the cursor */
182- int rc = stmt_reset (self -> statement );
186+ int rc = stmt_reset (self -> statement , 0 );
183187 Py_CLEAR (self -> statement );
184188 if (rc != SQLITE_OK ) {
185189 cursor_cannot_reset_stmt_error (self , 0 );
@@ -854,7 +858,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
854858
855859 if (self -> statement ) {
856860 // Reset pending statements on this cursor.
857- if (stmt_reset (self -> statement ) != SQLITE_OK ) {
861+ if (stmt_reset (self -> statement , 0 ) != SQLITE_OK ) {
858862 goto reset_failure ;
859863 }
860864 }
@@ -872,15 +876,18 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
872876 goto error ;
873877 }
874878
875- if (sqlite3_stmt_busy (self -> statement -> st )) {
879+ /* Reserve cached statements before releasing the GIL. SQLite only marks
880+ a statement busy once sqlite3_step() starts, leaving a race window. */
881+ if (!pysqlite_statement_try_mark_in_use (self -> statement )) {
876882 Py_SETREF (self -> statement ,
877883 pysqlite_statement_create (self -> connection , operation ));
878884 if (self -> statement == NULL ) {
879885 goto error ;
880886 }
887+ pysqlite_statement_mark_in_use (self -> statement , 1 );
881888 }
882889
883- if (stmt_reset (self -> statement ) != SQLITE_OK ) {
890+ if (stmt_reset (self -> statement , 1 ) != SQLITE_OK ) {
884891 goto reset_failure ;
885892 }
886893 self -> rowcount = self -> statement -> is_dml ? 0L : -1L ;
@@ -966,7 +973,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
966973 if (self -> statement -> is_dml ) {
967974 self -> rowcount += (long )sqlite3_changes (self -> connection -> db );
968975 }
969- if (stmt_reset (self -> statement ) != SQLITE_OK ) {
976+ if (stmt_reset (self -> statement , 0 ) != SQLITE_OK ) {
970977 goto reset_failure ;
971978 }
972979 }
@@ -1001,7 +1008,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation
10011008 int sqlite3_state = sqlite3_errcode (db );
10021009 // stmt_reset() may return a previously set exception,
10031010 // either triggered because of Python or sqlite3.
1004- rc = stmt_reset (self -> statement );
1011+ rc = stmt_reset (self -> statement , 0 );
10051012 Py_CLEAR (self -> statement );
10061013 if (sqlite3_state == SQLITE_OK && rc != SQLITE_OK ) {
10071014 cursor_cannot_reset_stmt_error (self , 1 );
@@ -1170,15 +1177,15 @@ pysqlite_cursor_iternext(PyObject *op)
11701177 if (self -> statement -> is_dml ) {
11711178 self -> rowcount = (long )sqlite3_changes (self -> connection -> db );
11721179 }
1173- rc = stmt_reset (self -> statement );
1180+ rc = stmt_reset (self -> statement , 0 );
11741181 Py_CLEAR (self -> statement );
11751182 if (rc != SQLITE_OK ) {
11761183 goto reset_failure ;
11771184 }
11781185 }
11791186 else if (rc != SQLITE_ROW ) {
11801187 rc = set_error_from_db (self -> connection -> state , self -> connection -> db );
1181- int reset_rc = stmt_reset (self -> statement );
1188+ int reset_rc = stmt_reset (self -> statement , 0 );
11821189 Py_CLEAR (self -> statement );
11831190 Py_DECREF (row );
11841191 if (rc == SQLITE_OK && reset_rc != SQLITE_OK ) {
@@ -1352,7 +1359,7 @@ pysqlite_cursor_close_impl(pysqlite_Cursor *self)
13521359 }
13531360
13541361 if (self -> statement ) {
1355- int rc = stmt_reset (self -> statement );
1362+ int rc = stmt_reset (self -> statement , 0 );
13561363 // Force self->statement to be NULL even if stmt_reset() may have
13571364 // failed to avoid a possible double-free if someone calls close()
13581365 // twice as a leak here would be better than a double-free.
0 commit comments