std::thread::join() hangs if called after main() exits when using VS2012 RC - by FraserH999

Status : 

  Fixed<br /><br />
		This item has been fixed in the current or upcoming version of this product.<br /><br />
		A more detailed explanation for the resolution of this particular item may have been provided in the comments section.

Sign in
to vote
ID 747145 Comments
Status Closed Workarounds
Type Bug Repros 11
Opened 6/6/2012 1:49:54 PM
Access Restriction Public


Running the following program compiled using VS 2012 RC causes the execution to hang at the join() call.

Uncommenting the last line fixes the problem.

#include <iostream>
#include <string>
#include <thread>

class ThreadTest {
  ThreadTest() : thread_([] { std::this_thread::sleep_for(std::chrono::milliseconds(10)); }) {}
  ~ThreadTest() { thread_.join(); }
  std::thread thread_;

int main() {
  static ThreadTest thread_test;
//  std::this_thread::sleep_for(std::chrono::milliseconds(100));

Sign in to post a comment.
Posted by VincentZeng on 7/22/2016 at 9:21 AM
Sorry, my std::thread::join() hangs is caused by console output log.

void MySprite::Thread_Routiue()
    //thread_running = false;
    while (thread_running) {
        log("vicent Thread_Routiue");

If I do not remove the log. The thread can not join.
Posted by VincentZeng on 7/18/2016 at 9:09 PM
The bug still found in VS2015.
Posted by Jim Barry on 11/23/2015 at 7:58 AM
For those like myself who are left stranded on VS2013 by Microsoft's lamentable decision not to provide upgrade pricing for VS2015, see my post in the Workarounds section.
Posted by Emily Le on 10/28/2014 at 3:29 AM
Please backport this fix to VS2013.

Visual Studio 2014 is not even available for purchase yet and you're already dropping support for VS2013. This is not the way to treat your paying customers.
Posted by Artur [MSFT] on 7/1/2014 at 10:15 AM
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.

Thanks for reporting this bug, and keep your feedback coming.
Posted by _Nebur_ on 9/23/2013 at 7:52 PM
Bug still exist in VC2013 RC. Will it be fixed any time soon?
Example code does block for ever in join after passing getchar.

#include "stdafx.h"
#include <thread>
#include <functional>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <MacroAux.h>
#include <DbgAux.h>

class AsyncWorker final
    using Job = std::function<void()>;
    AsyncWorker() :m_th{std::mem_fn(&AsyncWorker::Work), this} {}
        m_join = true;
        if(m_th.joinable()) m_th.join();
    template<typename T>
    void Enqueue(T&& job){*this += forward<T>(job);}
    template<typename T>
    AsyncWorker& operator<<(T&& job)
        std::lock_guard<std::mutex> lck(m_mtx);
        return *this;

    void Work()
            Job job;
                std::lock_guard<std::mutex> lck(m_mtx);
                if(!m_q.size()) m_wakeup.wait(m_mtx);
                if(m_q.size()) // double check, spurious wakeups
                    job = std::move(m_q.front());
            if(job) job();

    std::mutex m_mtx;
    std::queue<Job> m_q;
    std::condition_variable_any m_wakeup;
    std::atomic<bool> m_join = false;
    std::thread m_th;

template<typename T>
void AsyncDelete(T p)
    static AsyncWorker worker;
    worker <<[p] { delete p; };

int _tmain(int argc, _TCHAR* argv[])
    /*AsyncWorker worker;
    worker << [] { trace("lala1"); }
    << [] { trace("lala2"); }
    << [] { trace("lala3"); };*/

    AsyncDelete(new int);

    return 0;

Posted by Catalin Alexandru Zamfir on 9/13/2013 at 11:31 AM

Bug is affecting us also. We're allocating a singleton object, as static and using std::thread::join () in the destructor to call the join on the threads spawned by our object. What this bug does is actually hang the application at exit. Calling detach () on the threads gets the good functionality, but afaik, it may leak resources. This should be fixed urgently!
Posted by Stephan [MSFT] on 2/21/2013 at 1:50 PM

Thanks for reporting this bug. I wanted to let you know what's happening with it. I'm still keeping track of it, but it's been resolved as "Deferred" because we may not have time to fix it in VC12. (Note: VC8 = VS 2005, VC9 = VS 2008, VC10 = VS 2010, VC11 = VS 2012.)

Note: Connect doesn't notify me about comments. If you have any further questions, please E-mail me.

Stephan T. Lavavej
Senior Developer - Visual C++ Libraries
Posted by CMWoods on 11/21/2012 at 11:16 PM
I'm not sure that this bug has to do with the Concurrency Runtime. This looks like a straight forward deadlock case when tracing it with VS2012:

Main thread has acquired _EXIT_LOCK1, called ThreadTest destructor resulting in the join() call waiting [indefinitely] for second thread to exit.

Second thread completed but is waiting [indefinitely] to acquire _EXIT_LOCK1 in order to finish exiting.

Anything that delays the exit of the main() function long enough for the second thread to acquire _EXIT_LOCK1 first avoids the deadlock situation. Examples:

The uncommenting the sleep call which allows the second thread to complete.
Or alternatively removing static declaration on ThreadTest which then moves the destruction up to the exit of the main() function and blocks on the join() until the second thread has fully exited.
Posted by Stephan [MSFT] on 6/18/2012 at 3:25 PM

Thanks for reporting this bug. I'm Microsoft's maintainer of the STL, and I wanted to let you know that while this bug remains active in our database, it won't be fixed in VC11 RTM (VS 2012 RTM). All bugs are important to us, but some are more severe than others and rise to the top of our priority queue.

I'm copying-and-pasting this response across all of the STL's active Connect bugs, but the following terse comments apply specifically to your bug:

* I observe that while we're hanging, the Concurrency Runtime is calling Concurrency::details::_Timer::_Stop(). (std::mutex and other parts of our C++11 multithreading implementation are powered by ConcRT, and although std::thread itself directly wraps a HANDLE, launching one involves some ConcRT machinery.) We'll need to investigate further in order to figure out where the true problem is.

I can't promise when we'll be able to resolve this bug, but we hope to do so as soon as possible (and I'll send another response when that happens) - our first opportunity will be the "out of band" release between VC11 and VC12 that Herb Sutter announced at the GoingNative 2012 conference.

Note: Connect doesn't notify me about comments. If you have any further questions, please E-mail me.

Stephan T. Lavavej
Senior Developer - Visual C++ Libraries
Posted by Microsoft on 6/6/2012 at 11:35 PM
Thanks for your feedback.

We are rerouting this issue to the appropriate group within the Visual Studio Product Team for triage and resolution. These specialized experts will follow-up with your issue.
Posted by Microsoft on 6/6/2012 at 2:52 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(