diff --git a/src/greenlet/greenlet.cpp b/src/greenlet/greenlet.cpp index b40b8b53..78cfd0e4 100644 --- a/src/greenlet/greenlet.cpp +++ b/src/greenlet/greenlet.cpp @@ -13,9 +13,10 @@ #include "greenlet_internal.hpp" #include "greenlet_refs.hpp" +#include "greenlet_slp_switch.hpp" #include "greenlet_thread_state.hpp" #include "greenlet_thread_support.hpp" -#include "greenlet_slp_switch.hpp" + using std::swap; using std::cerr; using std::endl; @@ -1258,7 +1259,10 @@ class SwitchingState { */ if (err.status == 1) { /* in the new greenlet */ + // TODO: Move this to its own 'noexcept' function: + // C++ exceptions cannot propagate to the parent greenlet from here. assert(this->thread_state.borrow_current() == this->target); + this->thread_state.restore_exception_state(); /* stack variables from above are no good and also will not unwind! */ // EXCEPT: That can't be true, we access run, among others, here. diff --git a/src/greenlet/greenlet_thread_state.hpp b/src/greenlet/greenlet_thread_state.hpp index 17be9919..924b8dc9 100644 --- a/src/greenlet/greenlet_thread_state.hpp +++ b/src/greenlet/greenlet_thread_state.hpp @@ -109,6 +109,9 @@ class ThreadState { them. */ greenlet::g_deleteme_t deleteme; +#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED + void* exception_state; +#endif static ImmortalObject get_referrers_name; static PythonAllocator allocator; @@ -150,6 +153,21 @@ class ThreadState { if (!get_referrers_name) { ThreadState::get_referrers_name = Greenlet_Intern("get_referrers"); } +#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED + this->exception_state = slp_get_exception_state(); +#endif + } + + inline void restore_exception_state() + { +#ifdef GREENLET_NEEDS_EXCEPTION_STATE_SAVED + // temp debug + fprintf(stderr, "About to restore exception state in new greenlet. Current chain:\n"); + slp_show_seh_chain(); + slp_set_exception_state(this->exception_state); + fprintf(stderr, "Did restore exception state in new greenlet. Current chain:\n"); + slp_show_seh_chain(); +#endif } inline bool has_main_greenlet() diff --git a/src/greenlet/platform/switch_x86_msvc.h b/src/greenlet/platform/switch_x86_msvc.h index 6a16cfc8..087be907 100644 --- a/src/greenlet/platform/switch_x86_msvc.h +++ b/src/greenlet/platform/switch_x86_msvc.h @@ -79,7 +79,21 @@ * * Help would be appreciated. */ -#define GREENLET_CANNOT_USE_EXCEPTIONS_NEAR_SWITCH 1 +//#define GREENLET_CANNOT_USE_EXCEPTIONS_NEAR_SWITCH 1 + +#define GREENLET_NEEDS_EXCEPTION_STATE_SAVED + +static void* +slp_get_exception_state() +{ + return (void*)__readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList)); +} + +static void +slp_set_exception_state(const void *const seh_state) +{ + __writefsdword(FIELD_OFFSET(NT_TIB, ExceptionList), seh_state); +} typedef struct _GExceptionRegistration { struct _GExceptionRegistration* prev;