@@ -20,7 +20,6 @@ _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg)
2020PyFrameObject *
2121_PyFrame_MakeAndSetFrameObject (_PyInterpreterFrame * frame )
2222{
23- assert (frame -> frame_obj == NULL );
2423 PyObject * exc = PyErr_GetRaisedException ();
2524
2625 PyFrameObject * f = _PyFrame_New_NoTrack (_PyFrame_GetCode (frame ));
@@ -37,10 +36,18 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
3736 // Notice that _PyFrame_New_NoTrack() can potentially raise a MemoryError,
3837 // but it won't allocate a traceback until the frame unwinds, so we are safe
3938 // here.
40- assert (frame -> frame_obj == NULL );
4139 assert (frame -> owner != FRAME_OWNED_BY_FRAME_OBJECT );
4240 f -> f_frame = frame ;
41+ #ifdef Py_GIL_DISABLED
42+ PyFrameObject * expected = NULL ;
43+ if (!_Py_atomic_compare_exchange_ptr (& frame -> frame_obj , & expected , f )) {
44+ Py_DECREF (f );
45+ return expected ;
46+ }
47+ #else
48+ assert (frame -> frame_obj == NULL );
4349 frame -> frame_obj = f ;
50+ #endif
4451 return f ;
4552}
4653
@@ -113,9 +120,13 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
113120 // GH-99729: Clearing this frame can expose the stack (via finalizers). It's
114121 // crucial that this frame has been unlinked, and is no longer visible:
115122 assert (_PyThreadState_GET ()-> current_frame != frame );
116- if (frame -> frame_obj ) {
117- PyFrameObject * f = frame -> frame_obj ;
118- frame -> frame_obj = NULL ;
123+ #ifdef Py_GIL_DISABLED
124+ PyFrameObject * f = _Py_atomic_exchange_ptr (& frame -> frame_obj , NULL );
125+ #else
126+ PyFrameObject * f = frame -> frame_obj ;
127+ frame -> frame_obj = NULL ;
128+ #endif
129+ if (f != NULL ) {
119130 if (!_PyObject_IsUniquelyReferenced ((PyObject * )f )) {
120131 take_ownership (f , frame );
121132 Py_DECREF (f );
0 commit comments