@@ -2255,10 +2255,16 @@ _xidata_init(_PyCrossInterpreterData *data)
22552255static inline void
22562256_xidata_clear (_PyCrossInterpreterData * data )
22572257{
2258- if (data -> free != NULL ) {
2259- data -> free (data -> data );
2258+ // _PyCrossInterpreterData only has two members that need to be
2259+ // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
2260+ // In both cases the original (owning) interpreter must be used,
2261+ // which is the caller's responsibility to ensure.
2262+ if (data -> data != NULL ) {
2263+ if (data -> free != NULL ) {
2264+ data -> free (data -> data );
2265+ }
2266+ data -> data = NULL ;
22602267 }
2261- data -> data = NULL ;
22622268 Py_CLEAR (data -> obj );
22632269}
22642270
@@ -2403,40 +2409,32 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
24032409 return data -> new_object (data );
24042410}
24052411
2406- typedef void (* releasefunc )(PyInterpreterState * , void * );
2407-
2408- static void
2409- _call_in_interpreter (PyInterpreterState * interp , releasefunc func , void * arg )
2412+ static int
2413+ _release_xidata_pending (void * data )
24102414{
2411- /* We would use Py_AddPendingCall() if it weren't specific to the
2412- * main interpreter (see bpo-33608). In the meantime we take a
2413- * naive approach.
2414- */
2415- _PyRuntimeState * runtime = interp -> runtime ;
2416- PyThreadState * save_tstate = NULL ;
2417- if (interp != current_fast_get (runtime )-> interp ) {
2418- // XXX Using the "head" thread isn't strictly correct.
2419- PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
2420- // XXX Possible GILState issues?
2421- save_tstate = _PyThreadState_Swap (runtime , tstate );
2422- }
2423-
2424- // XXX Once the GIL is per-interpreter, this should be called with the
2425- // calling interpreter's GIL released and the target interpreter's held.
2426- func (interp , arg );
2415+ _xidata_clear ((_PyCrossInterpreterData * )data );
2416+ return 0 ;
2417+ }
24272418
2428- // Switch back.
2429- if (save_tstate != NULL ) {
2430- _PyThreadState_Swap (runtime , save_tstate );
2431- }
2419+ static int
2420+ _xidata_release_and_rawfree_pending (void * data )
2421+ {
2422+ _xidata_clear ((_PyCrossInterpreterData * )data );
2423+ PyMem_RawFree (data );
2424+ return 0 ;
24322425}
24332426
2434- int
2435- _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2427+ static int
2428+ _xidata_release (_PyCrossInterpreterData * data , int rawfree )
24362429{
2437- if (data -> free == NULL && data -> obj == NULL ) {
2430+ if (( data -> data == NULL || data -> free == NULL ) && data -> obj == NULL ) {
24382431 // Nothing to release!
2439- data -> data = NULL ;
2432+ if (rawfree ) {
2433+ PyMem_RawFree (data );
2434+ }
2435+ else {
2436+ data -> data = NULL ;
2437+ }
24402438 return 0 ;
24412439 }
24422440
@@ -2447,15 +2445,42 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
24472445 // This function shouldn't have been called.
24482446 // XXX Someone leaked some memory...
24492447 assert (PyErr_Occurred ());
2448+ if (rawfree ) {
2449+ PyMem_RawFree (data );
2450+ }
24502451 return -1 ;
24512452 }
24522453
24532454 // "Release" the data and/or the object.
2454- _call_in_interpreter (interp ,
2455- (releasefunc )_PyCrossInterpreterData_Clear , data );
2455+ if (interp == current_fast_get (interp -> runtime )-> interp ) {
2456+ _xidata_clear (data );
2457+ if (rawfree ) {
2458+ PyMem_RawFree (data );
2459+ }
2460+ }
2461+ else {
2462+ _Py_pending_call_func func = _release_xidata_pending ;
2463+ if (rawfree ) {
2464+ func = _xidata_release_and_rawfree_pending ;
2465+ }
2466+ // XXX Emit a warning if this fails?
2467+ _PyEval_AddPendingCall (interp , func , data , 0 );
2468+ }
24562469 return 0 ;
24572470}
24582471
2472+ int
2473+ _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2474+ {
2475+ return _xidata_release (data , 0 );
2476+ }
2477+
2478+ int
2479+ _PyCrossInterpreterData_ReleaseAndRawFree (_PyCrossInterpreterData * data )
2480+ {
2481+ return _xidata_release (data , 1 );
2482+ }
2483+
24592484/* registry of {type -> crossinterpdatafunc} */
24602485
24612486/* For now we use a global registry of shareable classes. An
0 commit comments