i have implemented a singleton (static version) in C++. I know all the controversy about this pattern and potential thread-safety issues, but i am curious why this exact implementation won't halt. The program never quits, it remains in a deadlock state at the end.
singleton.h:
#pragma once
#include <thread>
#include <atomic>
class Singleton
{
public:
static Singleton& getInstance();
private:
std::thread mThread;
std::atomic_bool mRun;
Singleton();
~Singleton();
void threadFoo();
};
singleton.cpp
#include "singleton.h"
Singleton& Singleton::getInstance()
{
static Singleton instance;
return instance;
}
Singleton::Singleton()
{
mRun.store(true);
mThread = std::thread(&Singleton::threadFoo, this);
}
Singleton::~Singleton()
{
mRun.store(false);
if(mThread.joinable())
mThread.join();
}
void Singleton::threadFoo()
{
while(mRun)
{
}
}
main.cpp
#include "singleton.h"
int main()
{
Singleton::getInstance();
return 0;
}
What I already know:
the thread terminates
the main thread is stuck in the join
it has something to do with the static, if i make the constructor public and create an instance of Singleton in main() it will correctly terminate.
Using Visual Studio 2012. Thanks for your advice.
On the main thread, after main() terminates, the CRT acquires the exit lock and calls your static instance destructor, which waits for your background thread to exit.
On the background thread, after your thread function terminates, the CRT attempts to acquire the exit lock to do some thread termination work. This blocks forever because the exit lock is held by the main thread, which is waiting for this thread to exit.
It's a simple deadlock that's caused by the CRT implementation. The bottom line is that you can't await thread termination in a static instance destructor on Windows.
I've traced it down to void __cdecl _lock(int locknum) inside mlock.c. When main() ends, the main thread goes there and enters critical section EnterCriticalSection( _locktable[locknum].lock );. Then Singleton destructor gets called and the other thread tries to enter the same critical section, but can't, and so it starts waiting for main thread to leave the critical section. Main thread, in turn, waits for the other thread. So I guess it's a bug.
See [basic.start.term] in the Standard:
If there is a use of a standard library object or function not
permitted within signal handlers (18.10) that does not happen before
(1.10) completion of destruction of objects with static storage
duration and execution of std::atexit registered functions (18.5), the
program has undefined behavior. [Note: If there is a use of an object
with static storage duration that does not happen before the object’s
destruction, the program has undefined behavior. Terminating every
thread before a call to std::exit or the exit from main is sufficient,
but not necessary, to satisfy these requirements. These requirements
permit thread managers as static-storage-duration objects. —end note ]
Ok thank you all for your hints. Apparently this pattern implementation results in a deadlock on VC++.
After doing some further research i found this implementation based on C++11 mechanics which is working in VC++.
singleton.h
#pragma once
#include <thread>
#include <atomic>
#include <memory>
#include <mutex>
class Singleton
{
public:
static Singleton& getInstance();
virtual ~Singleton();
private:
static std::unique_ptr<Singleton> mInstance;
static std::once_flag mOnceFlag;
std::thread mThread;
std::atomic_bool mRun;
Singleton();
void threadFoo();
};
singleton.cpp
#include "singleton.h"
std::unique_ptr<Singleton> Singleton::mInstance = nullptr;
std::once_flag Singleton::mOnceFlag;
Singleton& Singleton::getInstance()
{
std::call_once(mOnceFlag, [] { mInstance.reset(new Singleton); });
return *mInstance.get();
}
Singleton::Singleton()
{
mRun.store(true);
mThread = std::thread(&Singleton::threadFoo, this);
}
Singleton::~Singleton()
{
mRun.store(false);
if(mThread.joinable())
mThread.join();
}
void Singleton::threadFoo()
{
while(mRun.load())
{
}
}
UPDATE
It looks like Microsoft is aware of this issue. In the VC++ forums a user named "dlafleur" reported this post:
https://connect.microsoft.com/VisualStudio/feedback/details/747145
This deadlock bug is the same as in
std::thread::join() hangs if called after main() exits when using VS2012 RC
and it is not fixed in Visual Studio 2013.
It seems to be fixed in Visual Studio 2015 and above, at least for this specific example.
Related
I, for some reason, need to have a global object in a .dll, which manages a std::thread. It is implemented in a following way:
#include "Header.h"
#include <thread>
#include <condition_variable>
#include <mutex>
class Foo
{
public:
Foo () : m_closeThread (false)
{
m_thread = std::thread (&Foo::ThreadProc, this);
}
~Foo ()
{
{
std::unique_lock<std::mutex> lock (m_mutex);
m_closeThread = true;
}
m_cv.notify_one ();
m_thread.join ();
}
private:
void ThreadProc ()
{
while (true)
{
std::unique_lock<std::mutex> lock (m_mutex);
m_cv.wait (lock, [this] () { return m_closeThread; });
if (m_closeThread)
break;
}
}
private:
bool m_closeThread;
std::thread m_thread;
std::condition_variable m_cv;
std::mutex m_mutex;
};
Foo& GetFoo ()
{
static Foo foo;
return foo;
}
extern "C" void Function ()
{
auto& foo = GetFoo ();
}
However, when, the application is closed, before the ~Foo is executed, all worker threads, of the .dll, get killed, or as the output window of MSVS2015 says:
The thread 0x1040 has exited with code 0 (0x0).
And, due to this fact (Source0, Source1), the application blocks on m_cv.notify_one (); call, if one uses Windows 7 (doesn't block on Windows 8 and above).
The fact, that it blocks on one particular version of Windows, while not on others, makes me think, that some sort of UB is to blame (such as DLL unload ordering related issue, since such issue is not reproducible if such object is not in a .dll), but I fail to think of solution, that allows me to gracefully shutdown the thread, while having the object global (since, one would need to do major application restructuring, to make it not global).
So, can one shutdown the thread gracefully, before it is killed by the Windows platform?
Side note 0:
For the sake of example completeness,
this is the DLLMain:
#include <Windows.h>
BOOL APIENTRY DllMain (HMODULE, DWORD, LPVOID) { return TRUE; }
This is the Header of the .dll:
#pragma once
extern "C" void Function ();
This is the Console application, that uses said .dll:
#include "..\Test\Header.h"
#include <chrono>
#include <thread>
int main ()
{
Function ();
using namespace std::chrono_literals;
std::this_thread::sleep_for (2s);
}
Side note 1:
I am, currently limited to using, at most, C++11 (or, whatever functionality is present in MSVS 2015).
When WinMain returns, the runtime calls ExitProcess. The first thing that does is "1. All of the threads in the process, except the calling thread, terminate their execution without receiving a DLL_THREAD_DETACH notification."
I'm learning how to implement a thread safe singleton pattern in c++11 and later.
#include <iostream>
#include <memory>
#include <mutex>
class Singleton
{
public:
static Singleton& get_instance();
void print();
private:
static std::unique_ptr<Singleton> m_instance;
static std::once_flag m_onceFlag;
Singleton(){};
Singleton(const Singleton& src);
Singleton& operator=(const Singleton& rhs);
};
std::unique_ptr<Singleton> Singleton::m_instance = nullptr;
std::once_flag Singleton::m_onceFlag;
Singleton& Singleton::get_instance(){
std::call_once(m_onceFlag, [](){m_instance.reset(new Singleton());});
return *m_instance.get();
};
void Singleton::print(){
std::cout << "Something" << std::endl;
}
int main(int argc, char const *argv[])
{
Singleton::get_instance().print();
return 0;
}
The code compiles fine but when executing i receive the following Exception.
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted
i tried to debug the program with gdb. It seems that the exception is thrown when calling std::call_once. I'm not sure about what's happening but i assume that the lambda expression failed to create the object.
A second question. Is there a way to know what unknown error codes actually mean ? i think a -1 will not help much when trying to identify the problem.
Thanks for your help.
This happens because you did not compile with the -pthread flag and are attempting to use utilities from the native threading library on your system.
As an alternative look into the following change to the singleton pattern definition in your example referred to as the "Meyers Singleton"
Singleton& Singleton::get_instance(){
static Singleton instance;
return instance;
}
This is thread safe, and will cause the instance variable to only be initialized once. This wikipedia article has a good explanation of how it possibly works under the hood https://en.wikipedia.org/wiki/Double-checked_locking. It is good to let the compiler arrange code for you whenever possible. Also as noted in the comments this question also has useful information about the above Is Meyers' implementation of the Singleton pattern thread safe?
I have the following classes in my code.
In other words, There is a static object (singletone) which creates thread in CTor, and when its DTor is called, it has some work to be done in the context of this thread (DTor puts some jobs for the thread).
The problem that i face is that when the DTor of B is called there are no other threads running in the process - seems like this thread is killed by process cleanup before calling the destructor of class B.
Anyone knows why this happens? and how to avoid it?
UPD: The problems occures only when Singleton is created from DLL. All works fine when Singleton is created from the same executable.
I am using VS2017
Singleton.dll (A.h + A.cpp)
A.h -->
#pragma once
#include <thread>
class __declspec(dllexport) A
{
public:
static A* instance();
A();
~A();
private:
bool stopFlag;
std::thread mThread;
};
A.cpp
#include "stdafx.h"
#include <thread>
#include "A.h"
using namespace std;
A::A()
{
mThread = std::thread([this] { while (stopFlag == false) { } });
}
A::~A()
{
stopFlag = true;
mThread.join();
}
A* A::instance()
{
static A self;
return &self;
}
================================================================================
Executable which uses DLL
main.cpp
#include "stdafx.h"
#include "A.h"
int main()
{
auto a = A::instance();
return 0;
}
Updated with the compilable code. Now if you compile the first two files as DLL, and then put breakpoint in A's destructor, you will see that thread with lambda function does not exists....
UPDATE: Found an answer by myslef. In Windows, static object from DLL are unloaded ay very last point when all threads are already cleaned up
https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
Found an answer by myslef. In Windows, static object from DLL are unloaded ay very last point when all threads are already cleaned up https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
I am getting abort exception in simple VC++ program when main method completes.
Here is my sample test program.
#include "stdafx.h"
#include <thread>
#include <Windows.h>
class ThreadTest
{
public:
ThreadTest()
{
}
~ThreadTest()
{
}
void ThreadProc()
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ThreadTest test;
std::thread t = std::thread(&ThreadTest::ThreadProc, std::ref(test));
Sleep(5000);
return 0;
}
I have experience in nativate pthread_create functions but it seems that something is missing. When I put Sleep(15000); in ThreadProc method same issue happens without any changes.
This is documented in std::thread's destructor: if a thread is destroyed while it is joinable, std::terminate is called.
Quote from the C++11 standard draft n3290 (§30.3.1.3 thread destructor):
If joinable() then terminate(), otherwise no effects. [ Note: Either implicitly detaching or joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. — end note ]
You must either join the thread, or detach it. Joining seems like the right option in your case.
I am getting abort exception in simple VC++ program when main method completes.
Here is my sample test program.
#include "stdafx.h"
#include <thread>
#include <Windows.h>
class ThreadTest
{
public:
ThreadTest()
{
}
~ThreadTest()
{
}
void ThreadProc()
{
}
};
int _tmain(int argc, _TCHAR* argv[])
{
ThreadTest test;
std::thread t = std::thread(&ThreadTest::ThreadProc, std::ref(test));
Sleep(5000);
return 0;
}
I have experience in nativate pthread_create functions but it seems that something is missing. When I put Sleep(15000); in ThreadProc method same issue happens without any changes.
This is documented in std::thread's destructor: if a thread is destroyed while it is joinable, std::terminate is called.
Quote from the C++11 standard draft n3290 (§30.3.1.3 thread destructor):
If joinable() then terminate(), otherwise no effects. [ Note: Either implicitly detaching or joining a joinable() thread in its destructor could result in difficult to debug correctness (for detach) or performance (for join) bugs encountered only when an exception is raised. Thus the programmer must ensure that the destructor is never executed while the thread is still joinable. — end note ]
You must either join the thread, or detach it. Joining seems like the right option in your case.