@@ -2292,10 +2292,16 @@ _xidata_init(_PyCrossInterpreterData *data)
22922292static inline void
22932293_xidata_clear (_PyCrossInterpreterData * data )
22942294{
2295- if (data -> free != NULL ) {
2296- data -> free (data -> data );
2295+ // _PyCrossInterpreterData only has two members that need to be
2296+ // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
2297+ // In both cases the original (owning) interpreter must be used,
2298+ // which is the caller's responsibility to ensure.
2299+ if (data -> data != NULL ) {
2300+ if (data -> free != NULL ) {
2301+ data -> free (data -> data );
2302+ }
2303+ data -> data = NULL ;
22972304 }
2298- data -> data = NULL ;
22992305 Py_CLEAR (data -> obj );
23002306}
23012307
@@ -2440,40 +2446,32 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
24402446 return data -> new_object (data );
24412447}
24422448
2443- typedef void (* releasefunc )(PyInterpreterState * , void * );
2444-
2445- static void
2446- _call_in_interpreter (PyInterpreterState * interp , releasefunc func , void * arg )
2449+ static int
2450+ _release_xidata_pending (void * data )
24472451{
2448- /* We would use Py_AddPendingCall() if it weren't specific to the
2449- * main interpreter (see bpo-33608). In the meantime we take a
2450- * naive approach.
2451- */
2452- _PyRuntimeState * runtime = interp -> runtime ;
2453- PyThreadState * save_tstate = NULL ;
2454- if (interp != current_fast_get (runtime )-> interp ) {
2455- // XXX Using the "head" thread isn't strictly correct.
2456- PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
2457- // XXX Possible GILState issues?
2458- save_tstate = _PyThreadState_Swap (runtime , tstate );
2459- }
2460-
2461- // XXX Once the GIL is per-interpreter, this should be called with the
2462- // calling interpreter's GIL released and the target interpreter's held.
2463- func (interp , arg );
2452+ _xidata_clear ((_PyCrossInterpreterData * )data );
2453+ return 0 ;
2454+ }
24642455
2465- // Switch back.
2466- if (save_tstate != NULL ) {
2467- _PyThreadState_Swap (runtime , save_tstate );
2468- }
2456+ static int
2457+ _xidata_release_and_rawfree_pending (void * data )
2458+ {
2459+ _xidata_clear ((_PyCrossInterpreterData * )data );
2460+ PyMem_RawFree (data );
2461+ return 0 ;
24692462}
24702463
2471- int
2472- _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2464+ static int
2465+ _xidata_release (_PyCrossInterpreterData * data , int rawfree )
24732466{
2474- if (data -> free == NULL && data -> obj == NULL ) {
2467+ if (( data -> data == NULL || data -> free == NULL ) && data -> obj == NULL ) {
24752468 // Nothing to release!
2476- data -> data = NULL ;
2469+ if (rawfree ) {
2470+ PyMem_RawFree (data );
2471+ }
2472+ else {
2473+ data -> data = NULL ;
2474+ }
24772475 return 0 ;
24782476 }
24792477
@@ -2484,15 +2482,42 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
24842482 // This function shouldn't have been called.
24852483 // XXX Someone leaked some memory...
24862484 assert (PyErr_Occurred ());
2485+ if (rawfree ) {
2486+ PyMem_RawFree (data );
2487+ }
24872488 return -1 ;
24882489 }
24892490
24902491 // "Release" the data and/or the object.
2491- _call_in_interpreter (interp ,
2492- (releasefunc )_PyCrossInterpreterData_Clear , data );
2492+ if (interp == current_fast_get (interp -> runtime )-> interp ) {
2493+ _xidata_clear (data );
2494+ if (rawfree ) {
2495+ PyMem_RawFree (data );
2496+ }
2497+ }
2498+ else {
2499+ _Py_pending_call_func func = _release_xidata_pending ;
2500+ if (rawfree ) {
2501+ func = _xidata_release_and_rawfree_pending ;
2502+ }
2503+ // XXX Emit a warning if this fails?
2504+ _PyEval_AddPendingCall (interp , func , data , 0 );
2505+ }
24932506 return 0 ;
24942507}
24952508
2509+ int
2510+ _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2511+ {
2512+ return _xidata_release (data , 0 );
2513+ }
2514+
2515+ int
2516+ _PyCrossInterpreterData_ReleaseAndRawFree (_PyCrossInterpreterData * data )
2517+ {
2518+ return _xidata_release (data , 1 );
2519+ }
2520+
24962521/* registry of {type -> crossinterpdatafunc} */
24972522
24982523/* For now we use a global registry of shareable classes. An
0 commit comments