Weird std::thread bug on GCC 4.9 on ARM target

I have been dealing with Tizen development since about last year, and since then I have been learning of utilizing C++11 features on my codes. Currently I am developing a some kind of component to help performing message pump in threading, so you can dispatch a function to a queue to be performed in separate thread.

It is a simple components actually. You can take a look at GitHub. DispatchQueue class basically accepts functions to be queued to be executed in another thread. I uses std::deque to queue the tasks, and std::function to store lambda or other callable objects. To support the threading, I uses std::mutex for synchronization, as well as std::condition_variable to suspend thread during empty queue.

The code compiles flawlessly, but when I tried to run a Tizen native app using this component, the app directly crashed upon starting the DispatchQueue class. The worst part was that the call stack in crash log does not show that it was crashing in user code, but it shown that the signal was SIGABRT so it might be caused by an unhandled exception.

Because the DispatchQueue object is started during application start up, I have no time to attach debugger from Tizen Studio to examine it. To tackle this, I called std::this_thread::sleep_for rightaway to buy some time to attach debugger right after application start. For debugging, I tried to put breakpoints inside the MessageLoop function, so I can identify at which point the application crashes. But somehow when I perform debugging, there was no crash at all and the DispatchQueue worked flawlessly.

At that point I assumed that that was caused by a race condition at some point. But I have employed necessary measure to prevent race condition such as using std::mutex and std::unique_lock. I tried to modify the lock and it also does not work. The crash seemed to happen intermittently even when thread synchronization measures had been placed.

It took me 8 hours to realize that there was something wrong with using std::thread. I suspected that there’s some quirks in std::thread that caused this issue. I tried compiling with -pthread flag in my compiler option and it was still happening. Not after I tried using this piece of code, I finally could come into conclusion:

std::thread newThread { [] { std::cout << "In Thread\n"; } };
newThread.join();

And that very simple code crashed rightaway.

Digging through Google, I finally came across this GCC’s Bugzilla. On bottom of the thread someone pointed that this bug is still happening in GCC 4.9. As Tizen toolchain uses GCC 4.9 so I am out of luck of using std::thread for this case. It seems that there is race condition between main thread and the new thread when accessing vtable. In the glibc++ implementation on std::thread, I read that it utilizes a template class with virtual function Run as wrapper class for function object to be run on the thread.

Changing std::thread into pthread_create makes everything peaceful again.

Note: Tizen Studio utilizes LLVM 3.6 as frontend and GCC 4.9 as backend. It is also uses glibc++ but I am not really sure which version it is.

UPDATE 1 May 2019:

I rechecked the GCC Bugzilla link today, and found out that the issue has been fixed since November 2018, which is years after the issue started to surface. Apparently, there is an ABI (Application Binary Interface) conflict that causes this bug. The issue has been fixed and is expected to working correctly now, where perhaps many other users no longer care about this bug anymore and moved on with workarounds, lol.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *