@@ -108,18 +108,39 @@ int vmprof_snapshot_thread(DWORD thread_id, PY_WIN_THREAD_STATE *tstate, prof_st
108108 return depth ;
109109#else
110110
111- #if PY_VERSION_HEX >= 0x030B0000 /* < 3.11 */
112- _PyInterpreterFrame * frame = unsafe_PyThreadState_GetInterpreterFrame ( tstate ) ;
111+ #if PY_VERSION_HEX >= 0x030B0000 /* >= 3.11 */
112+ _PyInterpreterFrame * frame = NULL ;
113113#else
114- PY_STACK_FRAME_T * frame = PyThreadState_GetFrame ( tstate ) ;
114+ PY_STACK_FRAME_T * frame = NULL ;
115115#endif
116116
117- depth = vmp_walk_and_record_stack (frame , stack -> stack ,
118- MAX_STACK_DEPTH , 0 , 0 );
117+ /* The target thread was suspended at an arbitrary instruction, possibly
118+ in the middle of pushing or popping an interpreter frame, so the frame
119+ chain we are about to read may be inconsistent. Under MSVC, catch the
120+ resulting access violation and drop the sample instead of crashing. */
121+ #ifdef _MSC_VER
122+ __try {
123+ #endif
124+ #if PY_VERSION_HEX >= 0x030B0000 /* >= 3.11 */
125+ frame = unsafe_PyThreadState_GetInterpreterFrame (tstate );
126+ #else
127+ frame = PyThreadState_GetFrame (tstate );
128+ #endif
129+ depth = vmp_walk_and_record_stack (frame , stack -> stack ,
130+ MAX_STACK_DEPTH , 0 , 0 );
131+ #ifdef _MSC_VER
132+ } __except (EXCEPTION_EXECUTE_HANDLER ) {
133+ depth = -1 ;
134+ }
135+ #endif
119136
120137#if PY_VERSION_HEX < 0x030B0000 /* < 3.11 */
121138 Py_XDECREF (frame );
122139#endif
140+ if (depth < 0 ) {
141+ ResumeThread (hThread );
142+ return -1 ;
143+ }
123144 stack -> depth = depth ;
124145 stack -> stack [depth ++ ] = (void * )((ULONG_PTR )thread_id );
125146 stack -> count = 1 ;
0 commit comments