From 07ba2d6d95db2fe437f37da7c9f931a9cf22191b Mon Sep 17 00:00:00 2001 From: vogel76 Date: Sat, 8 Mar 2014 03:20:09 +0100 Subject: [PATCH 1/5] [BW]: [Fix] Include directories shall be specified through target_include_directories not just include_directories call. --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df294ed..e770c0c 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,7 +170,7 @@ IF(WIN32) # Needed to disable MSVC autolinking feature (#pragma comment) BOOST_ALL_NO_LIB ) - # Activate C++ exception handling inc. SEH to catch GPFs + # Activate C++ exception handling with SEH to allow catch GPFs target_compile_options(fc PUBLIC /EHa) ELSE() SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall" ) From fdbaf88e5e30b95be85c08f8c4cc2857420a62d9 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Sat, 8 Mar 2014 18:48:19 -0500 Subject: [PATCH 2/5] Provide a way to intercept Win32 structured exceptions in async tasks Something about the stacks created by boost::context prevents global structured exception handlers from being called. This allows the user to register a handler which will be called when there is an unhandled structured exception in async task. --- CMakeLists.txt | 4 ++-- include/fc/thread/task.hpp | 2 ++ include/fc/thread/thread.hpp | 24 ++++++++++++++++++++++++ src/thread/task.cpp | 16 ++++++++++++++++ src/thread/thread.cpp | 18 ++++++++++++++++-- 5 files changed, 60 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index df294ed..bcef70b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -174,8 +174,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..ec0f029 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 From 8b732263120b10d5246bef64df72efdbef25f820 Mon Sep 17 00:00:00 2001 From: HackFisher Date: Sun, 9 Mar 2014 16:18:00 +0800 Subject: [PATCH 3/5] This should be a typo, fix it. move ">" before #endif --- include/fc/thread/thread.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/thread/thread.hpp b/include/fc/thread/thread.hpp index ec0f029..e95a7d1 100644 --- a/include/fc/thread/thread.hpp +++ b/include/fc/thread/thread.hpp @@ -198,6 +198,6 @@ namespace fc { 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 } +#endif From 4c8b63f834402bba2b14a69347da2c754bec7886 Mon Sep 17 00:00:00 2001 From: Tzadik Vanderhoof Date: Sun, 9 Mar 2014 22:17:10 -0400 Subject: [PATCH 4/5] ignores --- .gitignore | 1 + 1 file changed, 1 insertion(+) 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 From e04d544016a61978ae7ed624058d76e972653df3 Mon Sep 17 00:00:00 2001 From: Eric Frias Date: Mon, 10 Mar 2014 17:37:38 -0400 Subject: [PATCH 5/5] Remove erroneous assert in fc::thread_d::check_for_timeouts() I believe this assert was being triggered when the only task on a thread did a fc::usleep (it might only have been when the sleep was of very short duration). --- src/thread/thread_d.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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();