diff --git a/.gitignore b/.gitignore index 25103bf..bbccfeb 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,4 @@ libfc_debug.a fc_automoc.cpp *.swp +GitSHA3.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index df294ed..c7e2fab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,10 +57,6 @@ ELSE(WIN32) SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.so") - include_directories( ${Boost_INCLUDE_DIR} ) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/vendor/salsa20 ) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ) - include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/vendor/easylzma/src ) IF(NOT APPLE ) # then unix # Unix build: SET(SALSA_SRC vendor/salsa20/salsa20.s) @@ -174,8 +170,8 @@ IF(WIN32) # Needed to disable MSVC autolinking feature (#pragma comment) BOOST_ALL_NO_LIB ) - # Activate C++ exception handling inc. SEH to catch GPFs - target_compile_options(fc PUBLIC /EHa) + # Activate C++ exception handling, assume extern C calls don't throw + target_compile_options(fc PUBLIC /EHsc) ELSE() SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall" ) diff --git a/include/fc/thread/task.hpp b/include/fc/thread/task.hpp index 664a5db..5c1b30e 100644 --- a/include/fc/thread/task.hpp +++ b/include/fc/thread/task.hpp @@ -33,6 +33,8 @@ namespace fc { void* _functor; void (*_destroy_functor)(void*); void (*_run_functor)(void*, void* ); + + void run_impl(); }; namespace detail { diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index eec4f72..e95a7d1 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -175,5 +175,29 @@ namespace fc { auto async( Functor&& f, const char* desc ="", priority prio = priority()) -> fc::future { return fc::thread::current().async( fc::forward(f), desc, prio ); } -} + +} // end namespace fc + +#ifdef _MSC_VER +struct _EXCEPTION_POINTERS; + +namespace fc { + /* There's something about the setup of the stacks created for fc::async tasks + * that screws up the global structured exception filters installed by + * SetUnhandledExceptionFilter(). The only way I've found to catch an + * unhaldned structured exception thrown in an async task is to put a + * __try/__except block inside the async task. + * We do just that, and if a SEH escapes outside the function running + * in the async task, fc will call an exception filter privided by + * set_unhandled_structured_exception_filter(), passing as arguments + * the result of GetExceptionCode() and GetExceptionInformation(). + * + * Right now there is only one global exception filter, used for any + * async task. + */ + typedef int (*unhandled_exception_filter_type)(unsigned, _EXCEPTION_POINTERS*); + void set_unhandled_structured_exception_filter(unhandled_exception_filter_type new_filter); + unhandled_exception_filter_type get_unhandled_structured_exception_filter(); +} +#endif diff --git a/src/thread/task.cpp b/src/thread/task.cpp index b963f2c..98edbd3 100644 --- a/src/thread/task.cpp +++ b/src/thread/task.cpp @@ -7,6 +7,11 @@ #include #include +#ifdef _MSC_VER +# include +# include +#endif + namespace fc { task_base::task_base(void* func) : @@ -18,6 +23,17 @@ namespace fc { } void task_base::run() { +#ifdef _MSC_VER + __try { +#endif + run_impl(); +#ifdef _MSC_VER + } __except (get_unhandled_structured_exception_filter() ? get_unhandled_structured_exception_filter()(GetExceptionCode(), GetExceptionInformation()) : EXCEPTION_CONTINUE_SEARCH) { + ExitProcess(1); + } +#endif + } + void task_base::run_impl() { try { _run_functor( _functor, _promise_impl ); } diff --git a/src/thread/thread.cpp b/src/thread/thread.cpp index 0a929eb..3ab54f6 100644 --- a/src/thread/thread.cpp +++ b/src/thread/thread.cpp @@ -381,5 +381,19 @@ namespace fc { return this == ¤t(); } - -} +#ifdef _MSC_VER + /* support for providing a structured exception handler for async tasks */ + namespace detail + { + unhandled_exception_filter_type unhandled_structured_exception_filter = nullptr; + } + void set_unhandled_structured_exception_filter(unhandled_exception_filter_type new_filter) + { + detail::unhandled_structured_exception_filter = new_filter; + } + unhandled_exception_filter_type get_unhandled_structured_exception_filter() + { + return detail::unhandled_structured_exception_filter; + } +#endif // _MSC_VER +} // end namespace fc diff --git a/src/thread/thread_d.hpp b/src/thread/thread_d.hpp index 9a93867..a23d922 100644 --- a/src/thread/thread_d.hpp +++ b/src/thread/thread_d.hpp @@ -430,9 +430,9 @@ namespace fc { else { //ilog( "..." ); - FC_ASSERT( c != current ) //ilog( "ready_push_front" ); - ready_push_front( c ); + if (c != current) + ready_push_front( c ); } } return time_point::min();