@@ -2259,10 +2259,16 @@ _xidata_init(_PyCrossInterpreterData *data)
22592259static inline void
22602260_xidata_clear (_PyCrossInterpreterData * data )
22612261{
2262- if (data -> free != NULL ) {
2263- data -> free (data -> data );
2262+ // _PyCrossInterpreterData only has two members that need to be
2263+ // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
2264+ // In both cases the original (owning) interpreter must be used,
2265+ // which is the caller's responsibility to ensure.
2266+ if (data -> data != NULL ) {
2267+ if (data -> free != NULL ) {
2268+ data -> free (data -> data );
2269+ }
2270+ data -> data = NULL ;
22642271 }
2265- data -> data = NULL ;
22662272 Py_CLEAR (data -> obj );
22672273}
22682274
@@ -2407,40 +2413,32 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
24072413 return data -> new_object (data );
24082414}
24092415
2410- typedef void (* releasefunc )(PyInterpreterState * , void * );
2411-
2412- static void
2413- _call_in_interpreter (PyInterpreterState * interp , releasefunc func , void * arg )
2416+ static int
2417+ _release_xidata_pending (void * data )
24142418{
2415- /* We would use Py_AddPendingCall() if it weren't specific to the
2416- * main interpreter (see bpo-33608). In the meantime we take a
2417- * naive approach.
2418- */
2419- _PyRuntimeState * runtime = interp -> runtime ;
2420- PyThreadState * save_tstate = NULL ;
2421- if (interp != current_fast_get (runtime )-> interp ) {
2422- // XXX Using the "head" thread isn't strictly correct.
2423- PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
2424- // XXX Possible GILState issues?
2425- save_tstate = _PyThreadState_Swap (runtime , tstate );
2426- }
2427-
2428- // XXX Once the GIL is per-interpreter, this should be called with the
2429- // calling interpreter's GIL released and the target interpreter's held.
2430- func (interp , arg );
2419+ _xidata_clear ((_PyCrossInterpreterData * )data );
2420+ return 0 ;
2421+ }
24312422
2432- // Switch back.
2433- if (save_tstate != NULL ) {
2434- _PyThreadState_Swap (runtime , save_tstate );
2435- }
2423+ static int
2424+ _xidata_release_and_rawfree_pending (void * data )
2425+ {
2426+ _xidata_clear ((_PyCrossInterpreterData * )data );
2427+ PyMem_RawFree (data );
2428+ return 0 ;
24362429}
24372430
2438- int
2439- _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2431+ static int
2432+ _xidata_release (_PyCrossInterpreterData * data , int rawfree )
24402433{
2441- if (data -> free == NULL && data -> obj == NULL ) {
2434+ if (( data -> data == NULL || data -> free == NULL ) && data -> obj == NULL ) {
24422435 // Nothing to release!
2443- data -> data = NULL ;
2436+ if (rawfree ) {
2437+ PyMem_RawFree (data );
2438+ }
2439+ else {
2440+ data -> data = NULL ;
2441+ }
24442442 return 0 ;
24452443 }
24462444
@@ -2451,15 +2449,42 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
24512449 // This function shouldn't have been called.
24522450 // XXX Someone leaked some memory...
24532451 assert (PyErr_Occurred ());
2452+ if (rawfree ) {
2453+ PyMem_RawFree (data );
2454+ }
24542455 return -1 ;
24552456 }
24562457
24572458 // "Release" the data and/or the object.
2458- _call_in_interpreter (interp ,
2459- (releasefunc )_PyCrossInterpreterData_Clear , data );
2459+ if (interp == current_fast_get (interp -> runtime )-> interp ) {
2460+ _xidata_clear (data );
2461+ if (rawfree ) {
2462+ PyMem_RawFree (data );
2463+ }
2464+ }
2465+ else {
2466+ int (* func )(void * ) = _release_xidata_pending ;
2467+ if (rawfree ) {
2468+ func = _xidata_release_and_rawfree_pending ;
2469+ }
2470+ // XXX Emit a warning if this fails?
2471+ _PyEval_AddPendingCall (interp , func , data , 0 );
2472+ }
24602473 return 0 ;
24612474}
24622475
2476+ int
2477+ _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2478+ {
2479+ return _xidata_release (data , 0 );
2480+ }
2481+
2482+ int
2483+ _PyCrossInterpreterData_ReleaseAndRawFree (_PyCrossInterpreterData * data )
2484+ {
2485+ return _xidata_release (data , 1 );
2486+ }
2487+
24632488/* registry of {type -> crossinterpdatafunc} */
24642489
24652490/* For now we use a global registry of shareable classes. An
0 commit comments