Why does this simple std::thread example not work? - c++

Tried the following example compiled with g++ -std=gnu++0x t1.cpp and g++ -std=c++0x t1.cpp but both of these result in the example aborting.
$ ./a.out
terminate called after throwing an instance of 'std::system_error'
what():
Aborted
Here is the sample:
#include <thread>
#include <iostream>
void doSomeWork( void )
{
std::cout << "hello from thread..." << std::endl;
return;
}
int main( int argc, char *argv[] )
{
std::thread t( doSomeWork );
t.join();
return 0;
}
I'm trying this on Ubuntu 11.04:
$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Anyone knows what I've missed?

You have to join std::threads, just like you have to join pthreads.
int main( int argc, char *argv[] )
{
std::thread t( doSomeWork );
t.join();
return 0;
}
UPDATE: This Debian bug report pointed me to the solution: add -pthread to your commandline. This is most probably a workaround until the std::thread code stabilizes and g++ pulls that library in when it should (or always, for C++).

Please use the pthread library during the compilation: g++ -lpthread.

Simplest code to reproduce that error and how to fix:
Put this in a file called s.cpp:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <thread>
using namespace std;
void task1(std::string msg){
cout << "task1 says: " << msg;
}
int main(){
std::thread t1(task1, "hello");
usleep(1000000);
t1.detach();
}
Compile like this:
el#apollo:~/foo7$ g++ -o s s.cpp -std=c++0x
Run it like this, the error happens:
el#apollo:~/foo7$ ./s
terminate called after throwing an instance of 'std::system_error'
what(): Operation not permitted
Aborted (core dumped)
To fix it, compile it like this with the -pthread flag:
g++ -o s s.cpp -std=c++0x -pthread
./s
Then it works correctly:
task1 says: hello

For what it's worth, I had different issue with similar code using threads in g++ (MinGW). Work-around was to put some "delay" between creating a thread and joining it.
Code with infrequently failing assertion:
std::atomic_bool flag{false};
std::thread worker( [&] () { flag.store(true); } );
worker.join();
assert(flag.load()); // Sometimes fails
Work-around:
std::atomic_bool flag{false};
std::thread worker( [&] () { flag.store(true); } );
while (not flag.load()) { std::this_thread::yield(); }
worker.join();
assert(flag.load()); // Works fine
Note that yield() alone did not help, hence the while loop. Using sleep_for(...) also works.

You need to link to run time library

Related

Linking to pthread or not determines the different behavior of the program

// main.cpp
#include <iostream>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
int main(int nArgCnt, char*ppArgs[]) {
using namespace std::chrono_literals;
std::mutex mtx;
std::unique_lock<decltype(mtx)> lock(mtx);
std::condition_variable condVar;
int x = 0;
condVar.wait(lock, [&] {
std::this_thread::sleep_for(1ms);
std::cout << x << std::endl;
return x > 0;
});
}
I build above code with g++ main.cpp -o test, the the test prints infinite lines:
0
0
0
0
...
However, if I built with g++ main.cpp -lpthread -o test, only one line is printed:
0
I have tested with different versions of Linux and different versions of g++ compilers, and got the same phenomenon.
Why adding -lpthread or not lead to different behavior of the code?
Ps. If I removed the line std::this_thread::sleep_for(1ms); , the test always print infinite lines whether -lpthread is added or not. So weird...

Is std::mutex recursive (ie non-reentrant)?

Test environment: Ubuntu 18.04.3 LTS g++ (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0.
Can std::mutex be reentrant? Why does the following test code 1 pass?
code1:
#include <iostream>
#include <mutex>
std::mutex g_mtx4val;
int g_val = 5;
void test() {
std::lock_guard<std::mutex> lck(g_mtx4val);
std::cout << "g_val=" << g_val << std::endl;
if (g_val > 0) {
--g_val;
test();
}
}
int main() {
test();
std::cout << "done ...." << std::endl;
return 0;
}
peanut#peanut:~/demo$ g++ test.cpp
peanut#peanut:~/demo$ ./a.out
g_val=5
g_val=4
g_val=3
g_val=2
g_val=1
g_val=0
done ...
code2:
// Same code 1
int main() {
std::thread t1(test);
t1.join();
std::cout << "done ...." << std::endl;
return 0;
}
peanut#peanut:~/demo$ g++ test2.cpp -lpthread
peanut#peanut:~/demo$ ./a.out
g_val=5
^C
peanut#peanut:~/demo$
code2 has a deadlock.
Why code1 can pass the test?
From the documentation page:
mutex offers exclusive, non-recursive ownership semantics
So the answer to the question in the title is no.
Can std::mutex be reentrant?
No, but if you want a recursive mutex, the std::recursive_mutex class provides that functionality.
Why does the following test code 1 pass?
What behavior were you expecting to see? The std::mutex documentation page simply says:
A calling thread must not own the mutex prior to calling lock or try_lock.
... it doesn't say what will happen if the calling thread breaks the above rule; which means that a program that breaks the rule may "appear to work", but even so is still incorrect and buggy.

Thread killed when application is backgrounded?

I'm developing a fuse filesystem and before calling fuse_main_real() I'm starting a std::thread in a class instance to do some background work.
this->t_receive = new std::thread([this] { this->receive(); });
However, it seems like fuse_main_real() kills this thread when going into background.
If I start the program with the -f option, which tells fuse to stay in the foreground, the problem does not occur and the thread survives.
I'm not sure what fuse does to go into background.
How do I make my thread survive being backgrounded?
Edit: Here's a basic example that exposes the problem:
#define FUSE_USE_VERSION 30
#include <iostream>
#include <thread>
#include <fuse.h>
static void thread_method()
{
while (true)
{
std::cout << "test" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
struct testop : fuse_operations
{ };
static struct testop ops;
int main(int argc, char** argv)
{
std::thread(thread_method).detach();
fuse_main_real(argc, argv, &ops, sizeof(fuse_operations), NULL);
}
Compile with
g++ -D_FILE_OFFSET_BITS=64 `pkg-config --cflags fuse` -lfuse -lpthread -std=c++14 -o test.o test.cpp
Command that works (repeatedly says "test"):
./test.o -f /home/test/testmountpoint
Command that doesn't work and shows the problem (says "test" once):
./test.o /home/test/testmountpoint
The libfuse wiki says that
Miscellaneous threads should be started from the init() method. Threads started before fuse_main() will exit when the process goes into the background.

Try-catch doesn't work in shared library?

(This is like my other question but this one is for another thing, even if it's related)
I've got a big issue in my project. I've got a library which handle XML and can throw exception. And, using it for creating a configuration file class show my first bug : exceptions aren't handled in the library, at all, and with every exception.
In the library I wrote :
try {
throw std::exception();
}
catch (...)
{
printf("caught\n");
}
But, the exception isn't handled and call std::terminate immediately :
terminate called after throwing an instance of 'std::exception'
what(): std::exception
The compilation flags are the simplest one : -fPIC -std=c++11 -g -Wall for the library, and -std=c++11 -g -Wall for the executable (plus the libraries and variant build defines). Also, I'm using G++ 5.4.0, under Linux (Linux Mint to be precise).
This is my main :
#include "ns/core/C_Configuration.hpp"
#include <iostream>
using namespace std;
using namespace ns;
int
main (int argc, char** argv)
{
try {
C_Configuration c ("test.xml");
c.load ("test.xml");
} catch (const std::exception& ex) {
cout << ex.what () << endl;
} catch (...) {
cout << "Caught." << endl;
}
return 0;
}
The C_Configuration.hpp :
#include <string>
#include <exception>
namespace ns
{
class C_Configuration
{
public:
C_Configuration (std::string);
bool load (std::string file);
};
} // namespace ns
And, this is the C_Configuration.cpp :
#include "ns/core/C_Configuration.hpp"
#include <cstdio>
using namespace std;
namespace ns
{
C_Configuration::C_Configuration (string)
{ }
bool
C_Configuration::load (string file)
{
try {
throw exception();
} catch (const exception& ex) {
printf ("In C_Configuration : %s\n", ex.what ());
} catch (...) {
printf ("In C_Configuration : caught\n");
}
return true;
}
} // namespace ns
Buid commands :
g++ -m64 -g -shared -fPIC -std=c++11 -o libns_framework.so C_Configuration.cpp
g++ -m64 -g -L. -o exe main.cpp -lns_framework
Note : I give this example, but it works as expected, the exception is caught in the library, not like in my main project. If you want to investigate more, you can check my project code here.
The problem is when :
The try-catch block is inside the library ;
The try-catch block is outside the library ;
In any case, the exception is thrown inside the library. But, exception thrown outside are caught in the executable code :
int
main (int argc, char** argv)
{
try {
throw 1;
} catch (...) {
cout << "Caught" << endl;
}
// Useless code
return 0;
}
This code just write Caught in the output.
So, my question is simple : Is C++ exception not handled within libraries, or I just forgot a compilation flag ? I need to say in the executable code, the exceptions work fine.
Thanks for your help.
EDIT : Oh god, my bad. Problem solved. Into the deepest part of my build configuration, an ld took the place of g++. Now the exception is working fine. Thanks for you help.
Simple. Never use ld with C++. I changed all ld commands in my project to g++ but seems I forgot for this library.
In short, I was using ld for building my library but g++ for the main executable. So the exceptions worked in the executable but not in the library because ld does not includes the C++ libraries which handle the exception system.
According to gcc manual:
if a library or main executable is supposed to throw or catch exceptions, you must link it using the G++ or GCJ driver, as appropriate for the languages used in the program, or using the option -shared-libgcc, such that it is linked with the shared libgcc.
Shared libraries (in C++ and Java) have that flag set by default, but not main executables. In any case, you should use it on both.
Test Case:
lib.cpp:
#include "lib.hpp"
#include <string>
#include <iostream>
using namespace std;
int function_throws_int() {
try {
throw 2;
}
catch (...) {
cout << "int throws lib" << endl;
throw;
}
return -1;
}
int function_throws_string() {
try {
throw std::string("throw");
}
catch (...) {
cout << "throws string lib" << endl;
throw;
}
}
lib.hpp:
int function_throws_int();
int function_throws_string();
Compile command line:
g++ -m64 -g -shared-libgcc -shared -fPIC -std=c++11 -o libtest.so lib.cpp
main.cpp:
#include "lib.hpp"
#include <string>
#include <iostream>
using namespace std;
int main(int argc, char ** argv) {
try {
function_throws_int();
}
catch (const string & e) {
cout << "string caught main" << endl;
}
catch (int i) {
cout << "int caught main" << endl;
}
return 0;
}
Compile command line:
g++ -m64 -g -shared-libgcc -o main -L. main.cpp -ltest
Execute:
LD_LIBRARY_PATH=. ./main
Output:
int throws lib
int caught main

Spurious wakeups on condition_variable with g++ and clang++

Take the following code:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
using namespace std;
int main() {
mutex m;
condition_variable c;
bool fired = false;
int i = 0;
// This thread counts the times the condition_variable woke up.
// If no spurious wakeups occur it should be close to 5.
thread t([&]() {
unique_lock<mutex> l(m);
while (!fired) {
c.wait_for(l, chrono::milliseconds(100));
++i;
}
});
// Here we wait for 500ms, then signal the other thread to stop
this_thread::sleep_for(chrono::milliseconds(500));
{
unique_lock<mutex> l(m);
fired = true;
c.notify_all();
cout << i << endl;
}
t.join();
}
Now, when I build this using clang++ -std=c++11 -pthread foo.cpp everything is fine, it outputs 4 on my machine. When I build it with g++ -std=c++11 -pthread foo.cpp however I get something very large every time, e.g. 81513. I realize the number of spurious wakeups is undefined, but I was surprised to see it so high.
Additional information: When I replace the wait_for by a simple wait both clang and g++ output 0.
Is this a bug / feature in g++? Why is it even different from clang? Can I get it to behave more reasonably?
Also: gcc version 4.7.3 (Debian 4.7.3-4).
I managed to get g++-4.8 running, and the problem is gone. Very weird, seems like a bug in g++-4.7.3, although I wasn't able to reproduce it on another machine.