@@ -2309,10 +2309,16 @@ _xidata_init(_PyCrossInterpreterData *data)
23092309static inline void
23102310_xidata_clear (_PyCrossInterpreterData * data )
23112311{
2312- if (data -> free != NULL ) {
2313- data -> free (data -> data );
2312+ // _PyCrossInterpreterData only has two members that need to be
2313+ // cleaned up, if set: "data" must be freed and "obj" must be decref'ed.
2314+ // In both cases the original (owning) interpreter must be used,
2315+ // which is the caller's responsibility to ensure.
2316+ if (data -> data != NULL ) {
2317+ if (data -> free != NULL ) {
2318+ data -> free (data -> data );
2319+ }
2320+ data -> data = NULL ;
23142321 }
2315- data -> data = NULL ;
23162322 Py_CLEAR (data -> obj );
23172323}
23182324
@@ -2457,40 +2463,32 @@ _PyCrossInterpreterData_NewObject(_PyCrossInterpreterData *data)
24572463 return data -> new_object (data );
24582464}
24592465
2460- typedef void (* releasefunc )(PyInterpreterState * , void * );
2461-
2462- static void
2463- _call_in_interpreter (PyInterpreterState * interp , releasefunc func , void * arg )
2466+ static int
2467+ _release_xidata_pending (void * data )
24642468{
2465- /* We would use Py_AddPendingCall() if it weren't specific to the
2466- * main interpreter (see bpo-33608). In the meantime we take a
2467- * naive approach.
2468- */
2469- _PyRuntimeState * runtime = interp -> runtime ;
2470- PyThreadState * save_tstate = NULL ;
2471- if (interp != current_fast_get (runtime )-> interp ) {
2472- // XXX Using the "head" thread isn't strictly correct.
2473- PyThreadState * tstate = PyInterpreterState_ThreadHead (interp );
2474- // XXX Possible GILState issues?
2475- save_tstate = _PyThreadState_Swap (runtime , tstate );
2476- }
2477-
2478- // XXX Once the GIL is per-interpreter, this should be called with the
2479- // calling interpreter's GIL released and the target interpreter's held.
2480- func (interp , arg );
2469+ _xidata_clear ((_PyCrossInterpreterData * )data );
2470+ return 0 ;
2471+ }
24812472
2482- // Switch back.
2483- if (save_tstate != NULL ) {
2484- _PyThreadState_Swap (runtime , save_tstate );
2485- }
2473+ static int
2474+ _xidata_release_and_rawfree_pending (void * data )
2475+ {
2476+ _xidata_clear ((_PyCrossInterpreterData * )data );
2477+ PyMem_RawFree (data );
2478+ return 0 ;
24862479}
24872480
2488- int
2489- _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2481+ static int
2482+ _xidata_release (_PyCrossInterpreterData * data , int rawfree )
24902483{
2491- if (data -> free == NULL && data -> obj == NULL ) {
2484+ if (( data -> data == NULL || data -> free == NULL ) && data -> obj == NULL ) {
24922485 // Nothing to release!
2493- data -> data = NULL ;
2486+ if (rawfree ) {
2487+ PyMem_RawFree (data );
2488+ }
2489+ else {
2490+ data -> data = NULL ;
2491+ }
24942492 return 0 ;
24952493 }
24962494
@@ -2501,15 +2499,42 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
25012499 // This function shouldn't have been called.
25022500 // XXX Someone leaked some memory...
25032501 assert (PyErr_Occurred ());
2502+ if (rawfree ) {
2503+ PyMem_RawFree (data );
2504+ }
25042505 return -1 ;
25052506 }
25062507
25072508 // "Release" the data and/or the object.
2508- _call_in_interpreter (interp ,
2509- (releasefunc )_PyCrossInterpreterData_Clear , data );
2509+ if (interp == current_fast_get (interp -> runtime )-> interp ) {
2510+ _xidata_clear (data );
2511+ if (rawfree ) {
2512+ PyMem_RawFree (data );
2513+ }
2514+ }
2515+ else {
2516+ _Py_pending_call_func func = _release_xidata_pending ;
2517+ if (rawfree ) {
2518+ func = _xidata_release_and_rawfree_pending ;
2519+ }
2520+ // XXX Emit a warning if this fails?
2521+ _PyEval_AddPendingCall (interp , func , data , 0 );
2522+ }
25102523 return 0 ;
25112524}
25122525
2526+ int
2527+ _PyCrossInterpreterData_Release (_PyCrossInterpreterData * data )
2528+ {
2529+ return _xidata_release (data , 0 );
2530+ }
2531+
2532+ int
2533+ _PyCrossInterpreterData_ReleaseAndRawFree (_PyCrossInterpreterData * data )
2534+ {
2535+ return _xidata_release (data , 1 );
2536+ }
2537+
25132538/* registry of {type -> crossinterpdatafunc} */
25142539
25152540/* For now we use a global registry of shareable classes. An
0 commit comments