none
Is it safe to use std::async(std::launch::async, ...) or std::thread with VS2013? RRS feed

  • Question

  • With "std::thread::join() hangs if called after main() exits when using VS2012 RC" a bug was reported to Microsoft and fixed with VS2015.

    My question: is it safe to spawn a new thread with std::thread as long as the thread object is NOT used as static/global object? Could the same problem also affect async "tasks" (futures) created with std::async and std::launch::async?

    EDIT/UPDATE:

    To support my question below an example that shows the problem. The reported problem still exists with VS2013 Update 4 (no problem when DeadlockOnApplicationExit() is deactivated and NoDeadlockOnApplicationExit() is activated):

    #include <iostream>
    #include <string>
    #include <thread>
    
    // example from https://connect.microsoft.com/VisualStudio/feedback/details/747145
    class ThreadTest {
    public:
      ThreadTest() : mThread([] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::cout << "ThreadTest running" << std::endl; }) {}
      ~ThreadTest() { mThread.join(); }
    private:
      std::thread mThread;
    };
    
    // shows the problem (ThreadTest as static function variable)
    void DeadlockOnApplicationExit()
    {
      static ThreadTest staticThreadTest;
      //std::this_thread::sleep_for(std::chrono::milliseconds(100)); //< a possible workaround from https://connect.microsoft.com/VisualStudio/feedback/details/747145
    }
    
    // no problem (ThreadTest as function variable)
    void NoDeadlockOnApplicationExit()
    {
      ThreadTest localThreadTest;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      std::cout << "main started" << std::endl;
      DeadlockOnApplicationExit();
      //NoDeadlockOnApplicationExit();
    
      std::cout << "exit of main" << std::endl;
      return 0;
    }

    I want to know if "this bug limited to the static/global usage of std::thread". Also I want to understand if there are differences between the use in DLLs and executable EXE (because of different unload behavior: https://blogs.msdn.microsoft.com/oldnewthing/20141017-00/?p=43823). My current assumption is that the problem is related to the "static" duration of the ThreadTest instance. (Static duration means that the object or variable is allocated when the program starts and is deallocated when the program ends.) But  currently I am not sure if that is really the case (maybe the execution time of the thread causes the problem and when the variable is not static the the problem just occurs less often). Finally IMHO problems like this should be officially documented - so I created this thread.


    • Edited by kth78 Wednesday, March 15, 2017 10:01 AM
    Monday, March 13, 2017 10:00 AM

All replies

  • Hi kth78,

    thanks for posting here.

    >>My question: is it safe to spawn a new thread with std::thread as long as the thread object is NOT used as static/global object? Could the same problem also affect async "tasks" (futures) created with std::async and std::launch::async?

    In my opinion, you could do that.

    Here is a document about calling a non-static member function as a thread function, you could refer to.

    https://www.codeproject.com/articles/16134/calling-a-non-static-member-function-as-a-thread-f

    Normally a non-static member function couldn't be called without a class instance. However, std::async forwards its argument to std::bind, and bind in turn can use std::mem_fn to turn a member function pointer into a functor that takes an explicit this parameter, so all you need to do is to pass this to the std::async invocation and use valid member function pointer syntax.

    Hope this could be help of you.

    Best Regards,

    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    • Edited by Baron Bi Tuesday, March 14, 2017 8:57 AM
    Tuesday, March 14, 2017 8:02 AM
  • Hi Sera Yu,

    I appreciate your reply, but I am more concerned if it is safe to use std::thread (and join) with Visual Studio 2013 (binding to non-static member function was not my question - but thanks).

    The MSDN page shows (currently) no warnings or remarks when I choose VS2012 or 2013:

    https://msdn.microsoft.com/en-us/library/hh920556%28v=vs.120%29.aspx

    But as Artur writes in the above referenced Microsoft connect Ticket, VS2012 and VS2013 have this problem:

    <copied_from_connect_ticket_747145>
    Hello there!
    
    I'm Artur Laksberg, I work with Stephan on the STL and other things. I fixed this
    bug in our private branch and the fix is on it's way to Dev14.
    
    If you're interested in details -- we're creating a critical section and scheduling
    its destruction under the atexit lock. We then scheduled the destruction of that
    critical section which also required taking the atexit lock, getting us into
    a deadlock.
    </copied_from_connect_ticket_747145>

    If you have good experience with std::thread and VS2013 or you can provide more details about the "atexit" lock that would be of help. :-)

    thx

    Tuesday, March 14, 2017 4:21 PM