@@ -328,28 +328,39 @@ PyInterpreterState_GetID(PyInterpreterState *interp)
328
328
}
329
329
330
330
331
- PyInterpreterState *
332
- _PyInterpreterState_LookUpID (PY_INT64_T requested_id )
331
+ static PyInterpreterState *
332
+ interp_look_up_id (PY_INT64_T requested_id )
333
333
{
334
- if (requested_id < 0 )
335
- goto error ;
336
-
337
334
PyInterpreterState * interp = PyInterpreterState_Head ();
338
335
while (interp != NULL ) {
339
336
PY_INT64_T id = PyInterpreterState_GetID (interp );
340
- if (id < 0 )
337
+ if (id < 0 ) {
341
338
return NULL ;
342
- if (requested_id == id )
339
+ }
340
+ if (requested_id == id ) {
343
341
return interp ;
342
+ }
344
343
interp = PyInterpreterState_Next (interp );
345
344
}
346
-
347
- error :
348
- PyErr_Format (PyExc_RuntimeError ,
349
- "unrecognized interpreter ID %lld" , requested_id );
350
345
return NULL ;
351
346
}
352
347
348
+ PyInterpreterState *
349
+ _PyInterpreterState_LookUpID (PY_INT64_T requested_id )
350
+ {
351
+ PyInterpreterState * interp = NULL ;
352
+ if (requested_id >= 0 ) {
353
+ HEAD_UNLOCK ();
354
+ interp = interp_look_up_id (requested_id );
355
+ HEAD_UNLOCK ();
356
+ }
357
+ if (interp == NULL && !PyErr_Occurred ()) {
358
+ PyErr_Format (PyExc_RuntimeError ,
359
+ "unrecognized interpreter ID %lld" , requested_id );
360
+ }
361
+ return interp ;
362
+ }
363
+
353
364
354
365
int
355
366
_PyInterpreterState_IDInitref (PyInterpreterState * interp )
@@ -1280,38 +1291,16 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
1280
1291
return 0 ;
1281
1292
}
1282
1293
1283
- static void
1294
+ static int
1284
1295
_release_xidata (void * arg )
1285
1296
{
1286
1297
_PyCrossInterpreterData * data = (_PyCrossInterpreterData * )arg ;
1287
1298
if (data -> free != NULL ) {
1288
1299
data -> free (data -> data );
1289
1300
}
1290
1301
Py_XDECREF (data -> obj );
1291
- }
1292
-
1293
- static void
1294
- _call_in_interpreter (PyInterpreterState * interp ,
1295
- void (* func )(void * ), void * arg )
1296
- {
1297
- /* We would use Py_AddPendingCall() if it weren't specific to the
1298
- * main interpreter (see bpo-33608). In the meantime we take a
1299
- * naive approach.
1300
- */
1301
- PyThreadState * save_tstate = NULL ;
1302
- if (interp != _PyInterpreterState_Get ()) {
1303
- // XXX Using the "head" thread isn't strictly correct.
1304
- PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
1305
- // XXX Possible GILState issues?
1306
- save_tstate = PyThreadState_Swap (tstate );
1307
- }
1308
-
1309
- func (arg );
1310
-
1311
- // Switch back.
1312
- if (save_tstate != NULL ) {
1313
- PyThreadState_Swap (save_tstate );
1314
- }
1302
+ PyMem_Free (data );
1303
+ return 0 ;
1315
1304
}
1316
1305
1317
1306
void
@@ -1322,7 +1311,7 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
1322
1311
return ;
1323
1312
}
1324
1313
1325
- // Switch to the original interpreter.
1314
+ // Get the original interpreter.
1326
1315
PyInterpreterState * interp = _PyInterpreterState_LookUpID (data -> interp );
1327
1316
if (interp == NULL ) {
1328
1317
// The intepreter was already destroyed.
@@ -1331,10 +1320,24 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
1331
1320
}
1332
1321
return ;
1333
1322
}
1323
+ // XXX There's an ever-so-slight race here...
1324
+ if (interp -> finalizing ) {
1325
+ // XXX Someone leaked some memory...
1326
+ return ;
1327
+ }
1334
1328
1335
1329
// "Release" the data and/or the object.
1336
- // XXX Use _Py_AddPendingCall().
1337
- _call_in_interpreter (interp , _release_xidata , data );
1330
+ _PyCrossInterpreterData * copied = PyMem_Malloc (sizeof (_PyCrossInterpreterData ));
1331
+ if (copied == NULL ) {
1332
+ PyErr_SetString (PyExc_MemoryError ,
1333
+ "Not enough memory to preserve cross-interpreter data" );
1334
+ PyErr_Print ();
1335
+ return ;
1336
+ }
1337
+ memcpy (copied , data , sizeof (_PyCrossInterpreterData ));
1338
+ if (_Py_AddPendingCall (interp , 0 , _release_xidata , copied ) != 0 ) {
1339
+ // XXX Queue full or couldn't get lock. Try again somehow?
1340
+ }
1338
1341
}
1339
1342
1340
1343
PyObject *
0 commit comments