Skip to content

Commit c3d4ac9

Browse files
committed
Simpler connection ownership
Replaced one extra ref with boxedcall owning the connection always, ensuring it is closed unless tp_init is successful
1 parent 4ef2d43 commit c3d4ac9

3 files changed

Lines changed: 7 additions & 16 deletions

File tree

apsw/tests/aiotest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ def hook(arg):
109109
BC.configure = BC.configure1
110110
BC.close = BC.close1
111111
self.assertRaisesRegex(RuntimeError, ".*only be called once.*", apsw.Connection.as_async, "")
112-
apsw.connections()[0].close()
112+
# we can't guarantee exactly when gc runs for the failure above
113+
if apsw.connections():
114+
apsw.connections()[0].close()
113115
self.assertIs(unraised.exc_type, ZeroDivisionError)
114116
unraised = None
115117
finally:

src/async.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ typedef struct BoxedCall
3131
PyObject *connection;
3232
PyObject *args;
3333
PyObject *kwargs;
34-
int call_success;
3534
} ConnectionInit;
3635

3736
/* note this must be the largest member of the union because
@@ -79,16 +78,9 @@ BoxedCall_clear(PyObject *self_)
7978
return;
8079

8180
case ConnectionInit:
82-
Py_DECREF(self->ConnectionInit.connection);
8381
Py_DECREF(self->ConnectionInit.args);
8482
Py_XDECREF(self->ConnectionInit.kwargs);
85-
if (!self->ConnectionInit.call_success)
86-
{
87-
/* this causes close on init failure so threads don't get leaked
88-
because our original code in as_async can't know about
89-
downstream failures */
90-
Py_DECREF(self->ConnectionInit.connection);
91-
}
83+
Py_DECREF(self->ConnectionInit.connection);
9284
break;
9385

9486
case FastCallWithKeywords: {
@@ -143,11 +135,8 @@ BoxedCall_internal_call(BoxedCall *self)
143135
if (0
144136
== Py_TYPE(self->ConnectionInit.connection)
145137
->tp_init(self->ConnectionInit.connection, self->ConnectionInit.args, self->ConnectionInit.kwargs))
146-
{
147138
result = Py_NewRef(self->ConnectionInit.connection);
148-
self->ConnectionInit.call_success = 1;
149-
}
150-
break;
139+
break;
151140
case FastCallWithKeywords:
152141
result = self->FastCallWithKeywords.function(
153142
self->FastCallWithKeywords.object, self->FastCallWithKeywords.fast_args + 1,

src/connection.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -805,10 +805,10 @@ Connection_as_async(PyObject *klass_, PyObject *args, PyObject *kwargs)
805805
if (!connection)
806806
goto error;
807807
boxed_call->call_type = ConnectionInit;
808-
boxed_call->ConnectionInit.connection = Py_NewRef((PyObject *)connection);
808+
/* the boxed call now owns the connection */
809+
boxed_call->ConnectionInit.connection = ((PyObject *)connection);
809810
boxed_call->ConnectionInit.args = Py_NewRef(args);
810811
boxed_call->ConnectionInit.kwargs = Py_XNewRef(kwargs);
811-
boxed_call->ConnectionInit.call_success = 0;
812812
connection->async_controller = NULL;
813813

814814
if(!PyContextVar_Get(async_controller_context_var, NULL, &connection->async_controller))

0 commit comments

Comments
 (0)