8000 Fix the channels module. · python/cpython@5316560 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5316560

Browse files
Fix the channels module.
1 parent 49e8fdc commit 5316560

File tree

2 files changed

+83
-97
lines changed

2 files changed

+83
-97
lines changed

Lib/test/support/interpreters/channels.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,5 +167,4 @@ def close(self):
167167
_channels.close(self._id, send=True)
168168

169169

170-
# XXX This is causing leaks (gh-110318):
171170
_channels._register_end_types(SendChannel, RecvChannel)

Modules/_xxinterpchannelsmodule.c

Lines changed: 83 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -93,35 +93,35 @@ API.. The module does not create any objects that are shared globally.
9393
PyMem_RawFree(VAR)
9494

9595

96-
struct xid_class_registry {
97-
size_t count;
98-
#define MAX_XID_CLASSES 5
99-
struct {
100-
PyTypeObject *cls;
101-
} added[MAX_XID_CLASSES];
96+
struct xid_types {
97+
/* Added at runtime by interpreters module. */
98+
PyTypeObject *SendChannel;
99+
PyTypeObject *RecvChannel;
100+
101+
/* heap types */
102+
PyTypeObject *ChannelID;
102103
};
103104

104-
static int
105-
register_xid_class(PyTypeObject *cls, crossinterpdatafunc shared,
106-
struct xid_class_registry *classes)
105+
static void
106+
clear_xid_types(struct xid_types *types)
107107
{
108-
int res = ensure_xid_class(cls, shared);
109-
if (res == 0) {
110-
assert(classes->count < MAX_XID_CLASSES);
111-
// The class has refs elsewhere, so we need to incref here.
112-
classes->added[classes->count].cls = cls;
113-
classes->count += 1;
108+
/* external types */
109+
if (types->SendChannel != NULL) {
110+
(void)_PyCrossInterpreterData_UnregisterClass(
111+
types->SendChannel);
112+
Py_CLEAR(types->SendChannel);
113+
}
114+
if (types->RecvChannel != NULL) {
115+
(void)_PyCrossInterpreterData_UnregisterClass(
116+
types->RecvChannel);
117+
Py_CLEAR(types->RecvChannel);
114118
}
115-
return res;
116-
}
117119

118-
static void
119-
clear_xid_class_registry(struct xid_class_registry *classes)
120-
{
121-
while (classes->count > 0) {
122-
classes->count -= 1;
123-
PyTypeObject *cls = classes->added[classes->count].cls;
124-
_PyCrossInterpreterData_UnregisterClass(cls);
120+
/* heap types */
121+
if (types->ChannelID != NULL) {
122+
(void)_PyCrossInterpreterData_UnregisterClass(
123+
types->ChannelID);
124+
Py_CLEAR(types->ChannelID);
125125
}
126126
}
127127

@@ -223,28 +223,6 @@ add_new_exception(PyObject *mod, const char *name, PyObject *base)
223223
#define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \
224224
add_new_exception(MOD, MODULE_NAME_STR "." Py_STRINGIFY(NAME), BASE)
225225

226-
static PyTypeObject *
227-
add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared,
228-
struct xid_class_registry *classes)
229-
{
230-
PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec(
231-
mod, spec, NULL);
232-
if (cls == NULL) {
233-
return NULL;
234-
}
235-
if (PyModule_AddType(mod, cls) < 0) {
236-
Py_DECREF(cls);
237-
return NULL;
238-
}
239-
if (shared != NULL) {
240-
if (register_xid_class(cls, shared, classes)) {
241-
Py_DECREF(cls);
242-
return NULL;
243-
}
244-
}
245-
return cls;
246-
}
247-
248226
static int
249227
wait_for_lock(PyThread_type_lock mutex, PY_TIMEOUT_T timeout)
250228
{
@@ -269,15 +247,10 @@ wait_for_lock(PyThread_type_lock mutex, PY_TIMEOUT_T timeout)
269247
/* module state *************************************************************/
270248

271249
typedef struct {
272-
struct xid_class_registry xid_classes;
273-
274-
/* Added at runtime by interpreters module. */
275-
PyTypeObject *send_channel_type;
276-
PyTypeObject *recv_channel_type;
250+
struct xid_types xid_types;
277251

278252
/* heap types */
279253
PyTypeObject *ChannelInfoType;
280-
PyTypeObject *ChannelIDType;
281254

282255
/* exceptions */
283256
PyObject *ChannelError;
@@ -315,12 +288,12 @@ static int
315288
traverse_module_state(module_state *state, visitproc visit, void *arg)
316289
{
317290
/* external types */
318-
Py_VISIT(state->send_channel_type);
319-
Py_VISIT(state->recv_channel_type);
291+
Py_VISIT(state->xid_types.SendChannel);
292+
Py_VISIT(state->xid_types.RecvChannel);
320293

321294
/* heap types */
322295
Py_VISIT(state->ChannelInfoType);
323-
Py_VISIT(state->ChannelIDType);
296+
Py_VISIT(state->xid_types.ChannelID);
324297

325298
/* exceptions */
326299
Py_VISIT(state->ChannelError);
@@ -335,16 +308,10 @@ traverse_module_state(module_state *state, visitproc visit, void *arg)
335308
static int
336309
clear_module_state(module_state *state)
337310
{
338-
/* external types */
339-
Py_CLEAR(state->send_channel_type);
340-
Py_CLEAR(state->recv_channel_type);
311+
clear_xid_types(&state->xid_types);
341312

342313
/* heap types */
343314
Py_CLEAR(state->ChannelInfoType);
344-
if (state->ChannelIDType != NULL) {
345-
(void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType);
346-
}
347-
Py_CLEAR(state->ChannelIDType);
348315

349316
/* exceptions */
350317
Py_CLEAR(state->ChannelError);
@@ -2210,7 +2177,7 @@ channel_id_converter(PyObject *arg, void *ptr)
22102177
struct channel_id_converter_data *data = ptr;
22112178
module_state *state = get_module_state(data->module);
22122179
assert(state != NULL);
2213-
if (PyObject_TypeCheck(arg, state->ChannelIDType)) {
2180+
if (PyObject_TypeCheck(arg, state->xid_types.ChannelID)) {
22142181
cid = ((channelid *)arg)->cid;
22152182
end = ((channelid *)arg)->end;
22162183
}
@@ -2406,14 +2373,14 @@ channelid_richcompare(PyObject *self, PyObject *other, int op)
24062373
goto done;
24072374
}
24082375

2409-
if (!PyObject_TypeCheck(self, state->ChannelIDType)) {
2376+
if (!PyObject_TypeCheck(self, state->xid_types.ChannelID)) {
24102377
res = Py_NewRef(Py_NotImplemented);
24112378
goto done;
24122379
}
24132380

24142381
channelid *cidobj = (channelid *)self;
24152382
int equal;
2416-
if (PyObject_TypeCheck(other, state->ChannelIDType)) {
2383+
if (PyObject_TypeCheck(other, state->xid_types.ChannelID)) {
24172384
channelid *othercidobj = (channelid *)other;
24182385
equal = (cidobj->end == othercidobj->end) && (cidobj->cid == othercidobj->cid);
24192386
}
@@ -2494,7 +2461,7 @@ _channelid_from_xid(_PyCrossInterpreterData *data)
24942461

24952462
// Note that we do not preserve the "resolve" flag.
24962463
PyObject *cidobj = NULL;
2497-
int err = newchannelid(state->ChannelIDType, xid->cid, xid->end,
2464+
int err = newchannelid(state->xid_types.ChannelID, xid->cid, xid->end,
24982465
_global_channels(), 0, 0,
24992466
(channelid **)&cidobj);
25002467
if (err != 0) {
@@ -2614,6 +2581,26 @@ static PyType_Spec channelid_typespec = {
26142581
.slots = channelid_typeslots,
26152582
};
26162583

2584+
static PyTypeObject *
2585+
add_channelid_type(PyObject *mod)
2586+
{
2587+
PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec(
2588+
mod, &channelid_typespec, NULL);
2589+
if (cls == NULL) {
2590+
return NULL;
2591+
}
2592+
if (ensure_xid_class(cls, _channelid_shared)) {
2593+
Py_DECREF(cls);
2594+
return NULL;
2595+
}
2596+
if (PyModule_AddType(mod, cls) < 0) {
2597+
(void)_PyCrossInterpreterData_UnregisterClass(cls);
2598+
Py_DECREF(cls);
2599+
return NULL;
2600+
}
2601+
return cls;
2602+
}
2603+
26172604

26182605
/* SendChannel and RecvChannel classes */
26192606

@@ -2628,11 +2615,11 @@ _get_current_channelend_type(int end)
26282615
}
26292616
PyTypeObject *cls;
26302617
if (end == CHANNEL_SEND) {
2631-
cls = state->send_channel_type;
2618+
cls = state->xid_types.SendChannel;
26322619
}
26332620
else {
26342621
assert(end == CHANNEL_RECV);
2635-
cls = state->recv_channel_type;
2622+
cls = state->xid_types.RecvChannel;
26362623
}
26372624
if (cls == NULL) {
26382625
// Force the module to be loaded, to register the type.
@@ -2646,10 +2633,10 @@ _get_current_channelend_type(int end)
26462633
}
26472634
Py_DECREF(highlevel);
26482635
if (end == CHANNEL_SEND) {
2649-
cls = state->send_channel_type;
2636+
cls = state->xid_types.SendChannel;
26502637
}
26512638
else {
2652-
cls = state->recv_channel_type;
2639+
cls = state->xid_types.RecvChannel;
26532640
}
26542641
assert(cls != NULL);
26552642
}
@@ -2697,23 +2684,30 @@ set_channelend_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
26972684
if (state == NULL) {
26982685
return -1;
26992686
}
2700-
struct xid_class_registry *xid_classes = &state->xid_classes;
2687+
struct xid_types *types = &state->xid_types;
27012688

2702-
if (state->send_channel_type != NULL
2703-
|| state->recv_channel_type != NULL)
2704-
{
2705-
PyErr_SetString(PyExc_TypeError, "already registered");
2706-
return -1;
2689+
// Clear the old values if the .py module was reloaded.
2690+
if (types->SendChannel != NULL) {
2691+
(void)_PyCrossInterpreterData_UnregisterClass(
2692+
types->SendChannel);
2693+
Py_CLEAR(types->SendChannel);
2694+
}
2695+
if (types->RecvChannel != NULL) {
2696+
(void)_PyCrossInterpreterData_UnregisterClass(
2697+
types->RecvChannel);
2698+
Py_CLEAR(types->RecvChannel);
27072699
}
2708-
state->send_channel_type = (PyTypeObject *)Py_NewRef(send);
2709-
state->recv_channel_type = (PyTypeObject *)Py_NewRef(recv);
27102700

2711-
if (register_xid_class(send, _channelend_shared, xid_classes)) {
2701+
// Add and register the new types.
2702+
if (ensure_xid_class(send, _channelend_shared) < 0) {
27122703
return -1;
27132704
}
2714-
if (register_xid_class(recv, _channelend_shared, xid_classes)) {
2705+
if (ensure_xid_class(recv, _channelend_shared) < 0) {
2706+
(void)_PyCrossInterpreterData_UnregisterClass(send);
27152707
return -1;
27162708
}
2709+
types->SendChannel = (PyTypeObject *)Py_NewRef(send);
2710+
types->RecvChannel = (PyTypeObject *)Py_NewRef(recv);
27172711

27182712
return 0;
27192713
}
@@ -2792,7 +2786,7 @@ channelsmod_create(PyObject *self, PyObject *Py_UNUSED(ignored))
27922786
return NULL;
27932787
}
27942788
PyObject *cidobj = NULL;
2795-
int err = newchannelid(state->ChannelIDType, cid, 0,
2789+
int err = newchannelid(state->xid_types.ChannelID, cid, 0,
27962790
&_globals.channels, 0, 0,
27972791
(channelid **)&cidobj);
27982792
if (handle_channel_error(err, self, cid)) {
@@ -2864,7 +2858,7 @@ channelsmod_list_all(PyObject *self, PyObject *Py_UNUSED(ignored))
28642858
int64_t *cur = cids;
28652859
for (int64_t i=0; i < count; cur++, i++) {
28662860
PyObject *cidobj = NULL;
2867-
int err = newchannelid(state->ChannelIDType, *cur, 0,
2861+
int err = newchannelid(state->xid_types.ChannelID, *cur, 0,
28682862
&_globals.channels, 0, 0,
28692863
(channelid **)&cidobj);
28702864
if (handle_channel_error(err, self, *cur)) {
@@ -3214,7 +3208,7 @@ channelsmod__channel_id(PyObject *self, PyObject *args, PyObject *kwds)
32143208
if (state == NULL) {
32153209
return NULL;
32163210
}
3217-
PyTypeObject *cls = state->ChannelIDType;
3211+
PyTypeObject *cls = state->xid_types.ChannelID;
32183212

32193213
PyObject *mod = get_module_from_owned_type(cls);
32203214
assert(mod == self);
@@ -3294,13 +3288,13 @@ module_exec(PyObject *mod)
32943288
if (_globals_init() != 0) {
32953289
return -1;
32963290
}
3297-
struct xid_class_registry *xid_classes = NULL;
3291+
struct xid_types *xid_types = NULL;
32983292

32993293
module_state *state = get_module_state(mod);
33003294
if (state == NULL) {
33013295
goto error;
33023296
}
3303-
xid_classes = &state->xid_classes;
3297+
xid_types = &state->xid_types;
33043298

33053299
/* Add exception types */
33063300
if (exceptions_init(mod) != 0) {
@@ -3319,9 +3313,8 @@ module_exec(PyObject *mod)
33193313
}
33203314

33213315
// ChannelID
3322-
state->ChannelIDType = add_new_type(
3323-
mod, &channelid_typespec, _channelid_shared, xid_classes);
3324-
if (state->ChannelIDType == NULL) {
3316+
xid_types->ChannelID = add_channelid_type(mod);
3317+
if (xid_types->ChannelID == NULL) {
33253318
goto error;
33263319
}
33273320

@@ -3332,8 +3325,8 @@ module_exec(PyObject *mod)
33323325
return 0;
33333326

33343327
error:
3335-
if (xid_classes != NULL) {
3336-
clear_xid_class_registry(xid_classes);
3328+
if (xid_types != NULL) {
3329+
clear_xid_types(xid_types);
33373330
}
33383331
_globals_fini();
33393332
return -1;
@@ -3360,9 +3353,6 @@ module_clear(PyObject *mod)
33603353
module_state *state = get_module_state(mod);
33613354
assert(state != NULL);
33623355

3363-
// Before clearing anything, we unregister the various XID types. */
3364-
clear_xid_class_registry(&state->xid_classes);
3365-
33663356
// Now we clear the module state.
33673357
clear_module_state(state);
33683358
return 0;
@@ -3374,9 +3364,6 @@ module_free(void *mod)
33743364
module_state *state = get_module_state(mod);
33753365
assert(state != NULL);
33763366

3377-
// Before clearing anything, we unregister the various XID types. */
3378-
clear_xid_class_registry(&state->xid_classes);
3379-
33803367
// Now we clear the module state.
33813368
clear_module_state(state);
33823369

0 commit comments

Comments
 (0)
0