@@ -146,7 +146,7 @@ static void _pysqlite_drop_unused_cursor_references(pysqlite_Connection* self);
146
146
static void free_callback_context (callback_context * ctx );
147
147
static void set_callback_context (callback_context * * ctx_pp ,
148
148
callback_context * ctx );
149
- static void connection_close (pysqlite_Connection * self );
149
+ static int connection_close (pysqlite_Connection * self );
150
150
PyObject * _pysqlite_query_execute (pysqlite_Cursor * , int , PyObject * , PyObject * );
151
151
152
152
static PyObject *
@@ -244,10 +244,13 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
244
244
}
245
245
246
246
if (self -> initialized ) {
247
+ self -> initialized = 0 ;
248
+
247
249
PyTypeObject * tp = Py_TYPE (self );
248
250
tp -> tp_clear ((PyObject * )self );
249
- connection_close (self );
250
- self -> initialized = 0 ;
251
+ if (connection_close (self ) < 0 ) {
252
+ return -1 ;
253
+ }
251
254
}
252
255
253
256
// Create and configure SQLite database object.
@@ -331,7 +334,9 @@ pysqlite_connection_init_impl(pysqlite_Connection *self, PyObject *database,
331
334
self -> initialized = 1 ;
332
335
333
336
if (autocommit == AUTOCOMMIT_DISABLED ) {
334
- (void )connection_exec_stmt (self , "BEGIN" );
337
+ if (connection_exec_stmt (self , "BEGIN" ) < 0 ) {
338
+ return -1 ;
339
+ }
335
340
}
336
341
return 0 ;
337
342
@@ -401,52 +406,88 @@ free_callback_contexts(pysqlite_Connection *self)
401
406
static void
402
407
remove_callbacks (sqlite3 * db )
403
408
{
409
+ assert (db != NULL );
410
+ /* None of these APIs can fail, as long as they are given a valid
411
+ * database pointer. */
412
+ int rc ;
404
413
#ifdef HAVE_TRACE_V2
405
- sqlite3_trace_v2 (db , SQLITE_TRACE_STMT , 0 , 0 );
414
+ rc = sqlite3_trace_v2 (db , SQLITE_TRACE_STMT , 0 , 0 );
415
+ assert (rc == SQLITE_OK ), (void )rc ;
406
416
#else
407
417
sqlite3_trace (db , 0 , (void * )0 );
408
418
#endif
419
+
409
420
sqlite3_progress_handler (db , 0 , 0 , (void * )0 );
410
- (void )sqlite3_set_authorizer (db , NULL , NULL );
421
+
422
+ rc = sqlite3_set_authorizer (db , NULL , NULL );
423
+ assert (rc == SQLITE_OK ), (void )rc ;
411
424
}
412
425
413
- static void
426
+ static int
414
427
connection_close (pysqlite_Connection * self )
415
428
{
416
- if (self -> db ) {
417
- if ( self -> autocommit == AUTOCOMMIT_DISABLED &&
418
- ! sqlite3_get_autocommit ( self -> db ))
419
- {
420
- /* If close is implicitly called as a result of interpreter
421
- * tear-down, we must not call back into Python. */
422
- if ( _Py_IsInterpreterFinalizing ( PyInterpreterState_Get ())) {
423
- remove_callbacks ( self -> db );
424
- }
425
- ( void ) connection_exec_stmt ( self , "ROLLBACK" ) ;
429
+ if (self -> db == NULL ) {
430
+ return 0 ;
431
+ }
432
+
433
+ int rc = 0 ;
434
+ if ( self -> autocommit == AUTOCOMMIT_DISABLED &&
435
+ ! sqlite3_get_autocommit ( self -> db ))
436
+ {
437
+ if ( connection_exec_stmt ( self , "ROLLBACK" ) < 0 ) {
438
+ rc = -1 ;
426
439
}
440
+ }
427
441
428
- free_callback_contexts (self );
442
+ sqlite3 * db = self -> db ;
443
+ self -> db = NULL ;
429
444
430
- sqlite3 * db = self -> db ;
431
- self -> db = NULL ;
445
+ Py_BEGIN_ALLOW_THREADS
446
+ /* The v2 close call always returns SQLITE_OK if given a valid database
447
+ * pointer (which we do), so we can safely ignore the return value */
448
+ (void )sqlite3_close_v2 (db );
449
+ Py_END_ALLOW_THREADS
432
450
433
- Py_BEGIN_ALLOW_THREADS
434
- int rc = sqlite3_close_v2 (db );
435
- assert (rc == SQLITE_OK ), (void )rc ;
436
- Py_END_ALLOW_THREADS
437
- }
451
+ free_callback_contexts (self );
452
+ return rc ;
438
453
}
439
454
440
455
static void
441
- connection_dealloc ( pysqlite_Connection * self )
456
+ connection_finalize ( PyObject * self )
442
457
{
443
- PyTypeObject * tp = Py_TYPE (self );
444
- PyObject_GC_UnTrack (self );
445
- tp -> tp_clear ((PyObject * )self );
458
+ pysqlite_Connection * con = (pysqlite_Connection * )self ;
459
+ PyObject * exc = PyErr_GetRaisedException ();
460
+
461
+ /* If close is implicitly called as a result of interpreter
462
+ * tear-down, we must not call back into Python. */
463
+ PyInterpreterState * interp = PyInterpreterState_Get ();
464
+ int teardown = _Py_IsInterpreterFinalizing (interp );
465
+ if (teardown && con -> db ) {
466
+ remove_callbacks (con -> db );
467
+ }
446
468
447
469
/* Clean up if user has not called .close() explicitly. */
448
- connection_close (self );
470
+ if (connection_close (con ) < 0 ) {
471
+ if (teardown ) {
472
+ PyErr_Clear ();
473
+ }
474
+ else {
475
+ PyErr_WriteUnraisable ((PyObject * )self );
476
+ }
477
+ }
478
+
479
+ PyErr_SetRaisedException (exc );
480
+ }
449
481
482
+ static void
483
+ connection_dealloc (PyObject * self )
484
+ {
485
+ if (PyObject_CallFinalizerFromDealloc (self ) < 0 ) {
486
+ return ;
487
+ }
488
+ PyTypeObject * tp = Py_TYPE (self );
489
+ PyObject_GC_UnTrack (self );
490
+ tp -> tp_clear (self );
450
491
tp -> tp_free (self );
451
492
Py_DECREF (tp );
452
493
}
@@ -594,7 +635,9 @@ pysqlite_connection_close_impl(pysqlite_Connection *self)
594
635
595
636
pysqlite_close_all_blobs (self );
596
637
Py_CLEAR (self -> statement_cache );
597
- connection_close (self );
638
+ if (connection_close (self ) < 0 ) {
639
+ return NULL ;
640
+ }
598
641
599
642
Py_RETURN_NONE ;
600
643
}
@@ -2582,6 +2625,7 @@ static struct PyMemberDef connection_members[] =
2582
2625
};
2583
2626
2584
2627
static PyType_Slot connection_slots [] = {
2628
+ {Py_tp_finalize , connection_finalize },
2585
2629
{Py_tp_dealloc , connection_dealloc },
2586
2630
{Py_tp_doc , (void * )connection_doc },
2587
2631
{Py_tp_methods , connection_methods },
0 commit comments