In the following program, during one thread (main) is performing thread::join, another thread (x) calls thread::detach:
#include <thread>
#include <iostream>
int main(void) {
auto t = std::thread([] {
std::this_thread::sleep_for( std::chrono::milliseconds(1000) );
} );
auto x = std::thread([&t] {
std::this_thread::sleep_for( std::chrono::milliseconds(500) );
if ( t.joinable() )
{
std::cout << "detaching t..." << std::endl;
t.detach();
}
} );
std::cout << "joining t..." << std::endl;
t.join();
x.join();
std::cout << "Ok" << std::endl;
return 0;
}
It work fine in GCC's libstdc++ and Clang's libc++ printing
joining t...
detaching t...
Ok
but in Visual Studio the program terminates with not-zero exit code before printing Ok. Online demo: https://gcc.godbolt.org/z/v1nEfaP7a
Is it a bug in Visual Studio or the program contains some undefined behavior?
Neither join nor detach are const-qualified and therefore the implementation is allowed to modify internal memory of the thread object without having to provide any guarantees of write/write or write/read data race avoidance on unsynchronized calls to these member functions per the default data race avoidance requirements of [res.on.data.races].
There is also no exception to this rule mentioned in [thread.threads] or anywhere else for these functions.
Therefore calling join and detach without establishing a happens-before relation between the two calls is a data race and causes undefined behavior.
Even without the detach call, there is still a write/read data race on the join/joinable pair of calls.
Related
I am trying to simulate the boost::thread's timed_join functionality (I know it's deprecated) with calling pthread_timedjoin_np on the native_handle of an std::thread. The problem is that despite joinable() returns true, the join() function throws.
#include <thread>
#include <chrono>
#include <iostream>
int main()
{
auto t = std::thread([]{
std::this_thread::sleep_for(std::chrono::milliseconds{100});
std::cout << "hello from thread\n";
});
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 1;
if (int s = pthread_timedjoin_np(t.native_handle(), nullptr, &ts); s != 0)
{
std::cout << "timed out: " << s << std::endl;
}
if(t.joinable())
{
std::cout << "thread is joinable\n";
t.join();
}
return 0;
}
Everything works if the spawned std::thread is still running when the pthread_timedjoin_np gets called and timed outs of course. Why is this strange behaviour? Isn't it possible to "manipulate" std::thread through its native handle?
If you go behind std::thread's back with native_handle, the standard library has no idea you've done this. Therefore, the result of thread::joinable is not reliable. Or more accurately, "implementation-defined". The implementation might check if the handle has been joined. Or it might not.
So if you intend to manipulate a thread outside of the standard library's control, you need to commit to it. The simplest way would be to have your pthread_timedjoin_np condition detach the thread object if it successfully joined.
I have few queries with respect to below code snapshot.
1) With respect to pthread_create(), assume Thread_1 creates Thread_2. To my understanding Thread_1 can exit without join, but still Thread_2 will keep running. Where as in below example without join() I am not able to run thread and I am seeing exceptions.
2) In few examples I am seeing thread creation without thread object as below. But when I do the same, code is terminated.
std::thread(&Task::executeThread, this);
I am compiling with below command.
g++ filename.cpp -std=c++11 -lpthread
But still it terminate with exception. Is this right way of creating thread or is there any different version of C++ (In my project already they are compiling but not sure about the version).
3) In few examples of my project code, I am seeing below way of creating thread. But I am not able to execute with below example.
std::thread( std::bind(&Task::executeThread, this) );
Below is my code snapshot.
#include <iostream>
#include <thread>
class Task
{
public:
void executeThread(void)
{
for(int i = 0; i < 5; i++)
{
std::cout << " :: " << i << std::endl;
}
}
void startThread(void);
};
void Task::startThread(void)
{
std::cout << "\nthis: " << this << std::endl;
#if 1
std::thread th(&Task::executeThread, this);
th.join(); // Without this join() or while(1) loop, thread will terminate
//while(1);
#elif 0
std::thread(&Task::executeThread, this); // Thread creation without thread object
#else
std::thread( std::bind(&Task::executeThread, this) );
while(1);
#endif
}
int main()
{
Task* taskPtr = new Task();
std::cout << "\ntaskPtr: " << taskPtr << std::endl;
taskPtr->startThread();
delete taskPtr;
return 0;
}
Thanks & Regards
Vishnu Beema
std::thread(&Task::executeThread, this); statement creates and destroys a thread object. The destructor of std::thread invokes std::terminate when the thread wasn't joined or detached (like in your statement).
There is no good reason to use std::bind in C++11 because lambdas are better in terms of space and speed.
When building multi-threaded code you need to specify -pthread option when both compiling and linking. Linker option -lpthread is both inadequate and unnecessary.
By design, you need to join all the threads you spawned, or detach them. See e.g. SO question on join/detach
See also cppreference, detach
Note also important caveats if main() exits while detached threads are still running
I also 100% agree with the comment in the other answer about preferring lambdas to bind.
Finally, do not fall for the temptation to do pthread_cancel on a thread in C++. See e.g pthread_cancel considered harmful
In C++ objects have a lifetime. This is a bit different then dealing with handles in C. In C++ if you create an object on the stack in one scope it will be destroyed if you exit that scope. There are some exception to these rule like std::move, but as a rule of thumb you own the lifetime of an object.
This ties into the same answer as above. When you called std::thread(&Task::executeThread, this); you were actually invoking the thread constructor. This is the start of the thread life and the object lifetime. Notice that you created this object on the stack. If you leave the scope { .. yourcode .. } the DTor will be called. Since you have done this before std::move, join or detatch then std::terminate() is called which is raising the exception.
You can create a thread that way. If you look at the linked documentation for std::thread::thread (constructor) there is an example of an object foo being created the same way. What errors are you receiving?
Relevant Documentation:
a. std::thread::~thread()
b. std::thread::thread
c. Lifetime in C++
I personally would recommend understanding the lifetime of objects in a C++. In short all objects start their lifetime when their constructor is invoked. When they are killed (as in out of scope) their destructor is called. The compiler handles this for you so if you're coming from C its a new concept.
Thank you all for your inputs. I missed thread object as part of thread creation. Because of this though compiling, I am getting exceptions. Below is my updated code. All three scenarios are working fine.
#include <iostream>
#include <thread>
class Task
{
public:
void executeThread(std::string command)
{
for(int i = 0; i < 5; i++)
{
std::cout << command << " :: " << i << std::endl;
}
}
void startThread(void);
std::thread th2;
std::thread th3;
};
void Task::startThread(void)
{
std::cout << "\nthis: " << this << std::endl;
#if 0
std::thread th1(&Task::executeThread, this, "Thread1");
th1.join(); // Without join(), thread will terminate
#elif 0
th2 = std::thread(&Task::executeThread, this, "Thread2");
th2.join();
#else
th3 = std::thread( std::bind(&Task::executeThread, this, "Thread3") );
th3.join();
#endif
}
int main()
{
Task* taskPtr = new Task();
std::cout << "\ntaskPtr: " << taskPtr << std::endl;
taskPtr->startThread();
delete taskPtr;
return 0;
}
I have following code which works in debug build not in the release build with g++ optimizations turned on. (When I say work, what I mean is when the main thread sets the flag stop to true, the looping thread exists).I know this issue can be fixed by adding volatile keyword. My question however is to understand what exactly is happening in this case. This is the code:
void main() {
bool stop = false;
std::thread reader_thread;
auto reader = [&]() {
std::cout << "starting reader" << std::endl;
//BindToCPU(reader_thread, 0);
while(!stop) {
}
std::cout << "exiting reader" << std::endl;
};
reader_thread = std::thread(reader);
sleep(2);
stop = true;
std::cout << "stopped" << std::endl;
reader_thread.join();
}
Why does this happen? Is it because compiler optimizations? Or is it because cache coherency issues? Some details on what exactly happens underneath is appreciated.
The behavior of the program is undefined. The problem is that two threads are both accessing the variable named stop, and one of them is writing to it. In the C++ standard, that's the definition of a data race, and the result is undefined behavior. To get rid of the data race you have to introduce synchronization in some form. The simplest way to do this is to change the type of stop from bool to std::atomic<bool>. Alternatively, you could use a mutex, but for this particular example, that would be overkill.
Marking stop as volatile might make the symptoms go away, but it does not fix the problem.
The problem is that the compiler, specifically the optimization phase cannot tell that the program actually does anything. In particular, it cannot tell that "stop" can ever be anything except false. The best and simplest solution is to make "stop" atomic. Here is the corrected program, with a bonus "sleep" routine at no extra charge.
#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
inline void std_sleep(long double seconds) noexcept
{
using duration_t = std::chrono::duration<long long, std::nano>;
const auto duration = duration_t(static_cast<long long> (seconds * 1e9));
std::this_thread::sleep_for(duration);
}
int main() {
std::atomic<bool> stop = false;
std::thread reader_thread;
auto reader = [&stop]() {
std::cout << "starting reader" << std::endl;
//BindToCPU(reader_thread, 0);
while(!stop) {
std_sleep(.25);
}
std::cout << "exiting reader" << std::endl;
};
reader_thread = std::thread(reader);
std_sleep(2.0);
stop = true;
std::cout << "stopped" << std::endl;
reader_thread.join();
return 0;
}
You have several threads which access the same variable, and one of them writes to the variable. This situation is called a data race. A data race is undefined behavior, and compilers tend to do funny/catastrophic things in these cases.
One example, which happens to match your description, is stated in here in section 2.3:
... violate the compiler's assumption that ordinary variables do not change without being assigned to ... If the variable is not annotated at all,
the loop waiting for another thread to set flag:
while (!flag) {}
could even be transformed to the, now likely infinite, but sequentially equivalent, loop:
tmp = flag; // tmp is local
while (!tmp) {}
Another article about this type of race condition is this one.
I wrote the following minimal example:
#include <iostream>
#include <cstring>
#include <pthread.h>
#define SUCCESS 0
using namespace std;
int main() {
int res;
pthread_mutex_t t;
pthread_mutex_init(&t, NULL);
res = pthread_mutex_lock(&t);
res = pthread_mutex_destroy(&t);
if (res != SUCCESS)
{
cout << "Failed to delete: " << strerror(res) << " # " << t.__data.__lock << " " << t.__data.__nusers << endl;
}
else
{
cout << "Deleted!"<< endl;
}
res = pthread_mutex_unlock(&t);
cout << res << endl;
pthread_exit(NULL);
return 0;
}
Also at ideone
On one side as someone noted, the standard apparently says
Attempting to destroy a locked mutex or a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.
So one could assume that if it the same thread then it's OK.
It's odd because this sentence was changed in the older version it was not there and the line said only
It shall be safe to destroy an initialized mutex that is unlocked. Attempting to destroy a locked mutex results in undefined behavior.
So it's not that far fetched to think that this change was made for a reason, I'm just trying to be sure.
I tested the previously mentioned code on two different linux systems(ubuntu 13.10 and another debian 5774) and it fails and prints "Failed to delete: Device or resource busy # 1 1" , where on ideone's platform it succeeds.
Is ideones' behavior is just a specific case of undefined behavior? Or is there something wrong with the other cases?
Unfortunately I couldn't find a source that specifically addresses this issue.
The quoted text:
Attempting to destroy a locked mutex or a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.
Should be interpreted with the "results in undefined behavior" clause distributed over the "or" conjunction. In other words:
Attempting to destroy a locked mutex results in undefined behavior.
and
Attempting to destroy a mutex that is referenced (for example, while being used in a pthread_cond_timedwait() or pthread_cond_wait()) by another thread results in undefined behavior.
The second version is significant, because when waiting on the condition variable, the associated mutex lock is released by the waiting thread.
I have some question about behavior of std::async function with std::launch::async policy & std::future object returned from async.
In following code, main thread waits for the completion of foo() on the thread created by async call.
#include <thread>
#include <future>
#include <iostream>
void foo()
{
std::cout << "foo:begin" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(10));
std::cout << "foo:done" << std::endl;
}
int main()
{
std::cout << "main:begin" << std::endl;
{
auto f = std::async(std::launch::async, foo);
// dtor f::~f blocks until completion of foo()... why??
}
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "main:done" << std::endl;
}
And I know http://www.stdthread.co.uk/doc/headers/future/async.html says
The destructor of the last future object associated with the
asynchronous state of the returned std::future shall block until the
future is ready.
My question is:
Q1. Does this behavior conform to the current C++ standard?
Q2. If Q1's answer is yes, which statements say that?
Yes, this is required by the C++ Standard. 30.6.8 [futures.async] paragraph 5, final bullet:
— the associated thread completion synchronizes with (1.10) the return from the first function that successfully detects the ready status of the shared state or with the return from the last function that releases the shared state, whichever happens first.
The destructor of the one and only std:future satisfies that condition, and so has to wait for the completion of the thread.