Commit f5a40a2f authored by Marius Wachtler's avatar Marius Wachtler

deinitFrame: don't modify CAPI exception state

If a CAPI exception was set and we called deinitFrame in some rare cases calling the finalizers cleared the CAPI exception.
This would cause us to return NULL even though no exception is set #1273 (for LLVM functions compiled in capi mode)
Unfortunately I could not come up with a testcase which triggers it but I verified that it fixes the problem scipy triggered.
parent a0affc4e
...@@ -253,16 +253,24 @@ void FrameInfo::disableDeinit(FrameInfo* replacement_frame) { ...@@ -253,16 +253,24 @@ void FrameInfo::disableDeinit(FrameInfo* replacement_frame) {
assert(isDisabledFrame()); assert(isDisabledFrame());
} }
extern "C" void deinitFrameMaybe(FrameInfo* frame_info) { extern "C" void deinitFrameMaybe(FrameInfo* frame_info) noexcept {
// Note: this has to match FrameInfo::disableDeinit // Note: this has to match FrameInfo::disableDeinit
if (!frame_info->isDisabledFrame()) if (!frame_info->isDisabledFrame())
deinitFrame(frame_info); deinitFrame(frame_info);
} }
extern "C" void deinitFrame(FrameInfo* frame_info) { extern "C" void deinitFrame(FrameInfo* frame_info) noexcept {
// This can fire if we have a call to deinitFrame() that should be to deinitFrameMaybe() instead // This can fire if we have a call to deinitFrame() that should be to deinitFrameMaybe() instead
assert(!frame_info->isDisabledFrame()); assert(!frame_info->isDisabledFrame());
Box* err_type, *err_value, *err_tb;
bool restore_exc = cur_thread_state.curexc_type != NULL;
if (restore_exc) {
// preserve the existing exception
PyErr_Fetch(&err_type, &err_value, &err_tb);
PyErr_Clear();
}
assert(cur_thread_state.frame_info == frame_info); assert(cur_thread_state.frame_info == frame_info);
cur_thread_state.frame_info = frame_info->back; cur_thread_state.frame_info = frame_info->back;
BoxedFrame* frame = frame_info->frame_obj; BoxedFrame* frame = frame_info->frame_obj;
...@@ -288,6 +296,10 @@ extern "C" void deinitFrame(FrameInfo* frame_info) { ...@@ -288,6 +296,10 @@ extern "C" void deinitFrame(FrameInfo* frame_info) {
} }
Py_CLEAR(frame_info->globals); Py_CLEAR(frame_info->globals);
assert(!PyErr_Occurred());
if (restore_exc)
PyErr_Restore(err_type, err_value, err_tb);
} }
int frameinfo_traverse(FrameInfo* frame_info, visitproc visit, void* arg) noexcept { int frameinfo_traverse(FrameInfo* frame_info, visitproc visit, void* arg) noexcept {
......
...@@ -1307,8 +1307,8 @@ FunctionMetadata* metadataFromCode(Box* code); ...@@ -1307,8 +1307,8 @@ FunctionMetadata* metadataFromCode(Box* code);
BORROWED(Box*) getFrame(FrameInfo* frame_info); BORROWED(Box*) getFrame(FrameInfo* frame_info);
BORROWED(Box*) getFrame(int depth); BORROWED(Box*) getFrame(int depth);
void frameInvalidateBack(BoxedFrame* frame); void frameInvalidateBack(BoxedFrame* frame);
extern "C" void deinitFrame(FrameInfo* frame_info); extern "C" void deinitFrame(FrameInfo* frame_info) noexcept;
extern "C" void deinitFrameMaybe(FrameInfo* frame_info); extern "C" void deinitFrameMaybe(FrameInfo* frame_info) noexcept;
int frameinfo_traverse(FrameInfo* frame_info, visitproc visit, void* arg) noexcept; int frameinfo_traverse(FrameInfo* frame_info, visitproc visit, void* arg) noexcept;
extern "C" void initFrame(FrameInfo* frame_info); extern "C" void initFrame(FrameInfo* frame_info);
extern "C" void setFrameExcInfo(FrameInfo* frame_info, STOLEN(Box*) type, STOLEN(Box*) value, STOLEN(Box*) tb); extern "C" void setFrameExcInfo(FrameInfo* frame_info, STOLEN(Box*) type, STOLEN(Box*) value, STOLEN(Box*) tb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment