After attempting to implement the necessary annotations to an existing codebase, I was unable to remove a seemingly simple warning. I backed into the most simple example, and still no joy.
I have cut-and-pasted the mutex.h header exactly as specified at Thread Safety Analysis. I cannot seem to do a scoped lock without producing a warning. Here is the code:
#include "mutex.h"
#include <iostream>
// functions added just to complete the implementation
void Mutex::Lock()
{
}
void Mutex::GenericUnlock()
{
}
// test a scoped lock
void do_something(Mutex &m)
{
auto locker = MutexLocker(&m);
std::cout << "Hello, world!\n";
}
int main(int argc, char** argv)
{
Mutex my_mutex;
do_something(my_mutex);
}
Compiling with clang++ -o thread_static_analysis thread_static_analysis.cpp -std=c++17 -Wthread-safety produces the following warning:
thread_static_analysis.cpp:18:1: warning: releasing mutex 'locker' that was not held [-Wthread-safety-analysis]
}
^
1 warning generated.
Either (1) I am missing something, or (2) this is a false-positive that must be ignored until a clang implementation issue is resolved. A search for such issues has as-yet given no useful results.
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
My understanding is that you are potentially creating a copy of temporary MutexLocker object in
auto locker = MutexLocker(&m);
(or thread safety analysis thinks you are creating it). The temporary is then destroyed and calls m.Unlock(). Then at the end of the function the locker object is destroyed and calls m.Unlock() again (thus causing a double release error).
The following code in a Visual Studio Professional 2019 project (version 16.3.6) produces a warning:
#include <thread>
#include <future>
class Foo {
public:
mutable std::recursive_mutex _writingMutex;
std::recursive_mutex& writingMutex() const { return _writingMutex; }
};
int main()
{
Foo a;
std::lock_guard<std::recursive_mutex> lock(a.writingMutex()); // produces C26110
std::lock_guard<std::recursive_mutex> lock2(a._writingMutex); // no warning
}
The first lock produces the warning C26110:
Warning C26110 Caller failing to hold lock 'lock' before calling function 'std::lock_guard::~lock_guard'
Why is this so? Does passing the mutex as reference not work?
Based on the compilation result of Alan and the comment of rustyx, I will answer my own question:
This is likely to be a code analysis bug in Visual Studio. Looks like C26110 can't recognize a mutex via a reference. The issue was reported here and I added my minimal example as comment there. The issue persists in the most recent version 16.3.7 as well
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 tried to build my application with ltalloc. I tried it with MinGW32 4.9.1 and MinGW64-32 4.9.2.
It compiles and links fine but when I run it a Segmentation Fault occurs. Debugging pinpointed the problem to the following code:
#include <pthread.h>
#pragma weak pthread_once
#pragma weak pthread_key_create
#pragma weak pthread_setspecific
static pthread_key_t pthread_key;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
static void init_pthread_key() { pthread_key_create(&pthread_key, release_thread_cache); }
static thread_local int thread_initialized = 0;
static void init_pthread_destructor()//must be called only when some block placed into a thread cache's free list
{
if (unlikely(!thread_initialized))
{
thread_initialized = 1;
if (pthread_once)
{
pthread_once(&init_once, init_pthread_key); // <--- THIS CAUSES THE SEGSEGV
pthread_setspecific(pthread_key, (void*)1);//set nonzero value to force calling of release_thread_cache() on thread terminate
}
}
}
As far as I know both versions support thread-local storage natively. The Wiki of of ltalloc also wrote the following:
Warning: in some builds of MinGW there is a problem with emutls and order of execution of thread destructor (all thread local variables destructed before it), and termination of any thread will lead to application crash.
Unfortunately this warning doesn't tell me anything. Googling it also didn't make me smarter.
Out of the blue, try this:
static void init_pthread_key(void)
{
if (pthread_key_create)
{
pthread_key_create(&pthread_key, release_thread_cache);
}
}
Also adding full error checking to the pthread_* might not only help during debugging.
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.