boostorg / thread

Boost.org thread module
http://boost.org/libs/thread
203 stars 162 forks source link

VS 2017.4 Preview executor_ex.exe deadlock #137

Closed garyfurnish closed 7 years ago

garyfurnish commented 7 years ago

Deadlock requires end-task to continue tests. Produced in 3222938 with 2017.4 preview, suspect also occurs in 2017.3. Tested in debug, address-model=64. Maybe related to #134 and #135 and #136 All Threads appear to be stuck on thread.cpp line 741. Main thread call stack:

    [External Code]     Annotated Frame
>   boost_thread-vc141-mt-gd-1_65.dll!boost::this_thread::interruptible_wait(void * handle_to_wait_for, boost::detail::timeout target_time) Line 741    C++ Symbols loaded.
    boost_thread-vc141-mt-gd-1_65.dll!boost::thread::join_noexcept() Line 453   C++ Symbols loaded.
    ex_executor.exe!boost::thread::join() Line 775  C++ Symbols loaded.
    ex_executor.exe!boost::executors::basic_thread_pool::join() Line 238    C++ Symbols loaded.
    ex_executor.exe!boost::executors::basic_thread_pool::~basic_thread_pool() Line 227  C++ Symbols loaded.
    [External Code]     Annotated Frame
    ex_executor.exe!test_executor_adaptor() Line 121    C++ Symbols loaded.
    ex_executor.exe!main() Line 207 C++ Symbols loaded.
    [External Code]     Annotated Frame

Worker thread:

    [External Code]     Annotated Frame
>   boost_thread-vc141-mt-gd-1_65.dll!boost::this_thread::interruptible_wait(void * handle_to_wait_for, boost::detail::timeout target_time) Line 741    C++ Symbols loaded.
    ex_executor.exe!boost::detail::basic_cv_list_entry::wait(boost::detail::timeout abs_time) Line 95   C++ Symbols loaded.
    ex_executor.exe!boost::detail::basic_condition_variable::do_wait<boost::unique_lock<boost::mutex> >(boost::unique_lock<boost::mutex> & lock, boost::detail::timeout abs_time) Line 245  C++ Symbols loaded.
    ex_executor.exe!boost::condition_variable::wait(boost::unique_lock<boost::mutex> & m) Line 339  C++ Symbols loaded.
    ex_executor.exe!boost::concurrent::detail::sync_queue_base<boost::detail::nullary_function<void __cdecl(void)>,boost::csbl::devector<boost::detail::nullary_function<void __cdecl(void)> > >::wait_until_not_empty_or_closed(boost::unique_lock<boost::mutex> & lk) Line 201    C++ Symbols loaded.
    ex_executor.exe!boost::concurrent::sync_queue<boost::detail::nullary_function<void __cdecl(void)>,boost::csbl::devector<boost::detail::nullary_function<void __cdecl(void)> > >::wait_pull(boost::detail::nullary_function<void __cdecl(void)> & elem, boost::unique_lock<boost::mutex> & lk) Line 161  C++ Symbols loaded.
    ex_executor.exe!boost::concurrent::sync_queue<boost::detail::nullary_function<void __cdecl(void)>,boost::csbl::devector<boost::detail::nullary_function<void __cdecl(void)> > >::wait_pull(boost::detail::nullary_function<void __cdecl(void)> & elem) Line 181 C++ Symbols loaded.
    ex_executor.exe!boost::executors::basic_thread_pool::worker_thread() Line 89    C++ Symbols loaded.
    ex_executor.exe!boost::detail::invoke<void (__cdecl boost::executors::basic_thread_pool::*)(void) __ptr64,boost::executors::basic_thread_pool * __ptr64>(void(boost::executors::basic_thread_pool::*)() && f, boost::executors::basic_thread_pool * && a0) Line 78  C++ Symbols loaded.
    ex_executor.exe!boost::detail::thread_data<void (__cdecl boost::executors::basic_thread_pool::*)(void) __ptr64,boost::executors::basic_thread_pool * __ptr64>::run2<1>(boost::detail::tuple_indices<1> __formal) Line 76    C++ Symbols loaded.
    ex_executor.exe!boost::detail::thread_data<void (__cdecl boost::executors::basic_thread_pool::*)(void) __ptr64,boost::executors::basic_thread_pool * __ptr64>::run() Line 82    C++ Symbols loaded.
    boost_thread-vc141-mt-gd-1_65.dll!boost::`anonymous namespace'::thread_start_function(void * param) Line 296    C++ Symbols loaded.
    [External Code]     Annotated Frame

Will make some dumps if needed.

garyfurnish commented 7 years ago

See also deadlock in ex_generic_executor_ref.exe Also ex_serial_executor.exe Also ex_parallel_quick_sort_lib.exe Also ex_fib_task_region.exe Also task_region_p.exe

viboes commented 7 years ago

Do you know if the last VS versions don't define BOOST_NO_SFINAE_EXPR?

viboes commented 7 years ago

I suspect that there is a missing thread::interrupt before the call to join

    void join()
    {
      for (unsigned i = 0; i < threads.size(); ++i)
      {
        threads[i].interrupt(); // missing
        threads[i].join();
      }
    }
garyfurnish commented 7 years ago

My understanding is BOOST_NO_SFINAE_EXPR is not set but BOOST_NO_CXX11_SFINAE_EXPR is set.
I made the change to executors/basic_thread_pool.hpp (I'm assuming that is what you are talking about) and that appears to cause termination in basic_thread_pool::worker_thread. If thats not what you are talking about I'm not sure where it is missing from.

viboes commented 7 years ago

Yes, I need to catch the thread_interrupted exception :)

garyfurnish commented 7 years ago

Ok if you put up a patch I'll test it tomorrow.

viboes commented 7 years ago

https://github.com/boostorg/thread/commit/39c23ddf5a3082d76ebda107dce02fb86e948cd4

garyfurnish commented 7 years ago

Tests clean and closing as fixed by 39c23dd.

viboes commented 7 years ago

Thanks a lot for reporting those issues.