This question already has answers here:
Starting thread causing abort()
(2 answers)
std::thread causes program to abort
(1 answer)
Closed 1 year ago.
Why using delete in a thread fails, but not if called synchronously ?
class dummyclass{};
main()
{
vector<dummyclass*> testlist{};
for(int i=0; i<5; i++)
{
auto value = new dummyclass();
testlist.push_back(value);
}
thread cleanuptest([&]() {for (auto x : testlist) delete x;}); // fails (abort())
}
EDIT/COMMENT
detach and join are the right solutions.
In the case main() is actually a method in a bigger program, which continues to live, detach() is interesting.
In the case of unit tests, then calling join() in the destructor of the class to test is cleaner.
The problem with your program is that your main() function exits before the cleanuptest() thread has a chance to run to completion, taking the testlist object with it. So when cleanuptest() runs, it will likely be trying to access a vector that has already been destroyed (or is in the process of being destroyed, depending on the timing of when the threads execute; they are running asynchronously with respect to each other so their relative timing is indeterminate).
The other problem (which is likely the source of the abort() call) is that the std::thread destructor is detecting that you are destroying the thread object without having called either join() or detach() on it first, which is considered a programming error.
The fix is easy, just add this line to the bottom of main():
cleanuptest.join();
The join() method won't return until the child thread has exited, so it will guarantee that testlist remains valid until the child thread is done using it.
Your main is finishing before the thread has a chance to finish which is causing the abort. You should cleanuptest.join() the thread to let it finish before main exits.
Related
This question already has answers here:
How does thread::detach() work in C++11?
(2 answers)
What happens to a detached thread when main() exits?
(7 answers)
Closed 1 year ago.
I am writing the following c++ code to create a detach thread :
void threadF() {
ofstream f("data") ;
for(int i=1; i<=5; i++) {
f<<"t1:::"<<i<<"\n" ;
f.flush() ;
sleep(1) ;
}
f.close() ;
}
int main() {
thread t1(threadF) ;
cout<<"main #1\n" ;
sleep(2) ;
t1.detach() ;
cout<<"main #2\n" ;
}
When I run this code, I have the following observations :
main exits after 2 secs (as expected)
the detach child thread also seems to be running only for 2secs because the output data file contains only 2 lines.
I expected that the thread should have executed completely and that the output data file should have contained 5 lines. This is not happening
I need an explanation for this behavior.
AS per the ink What happens to a detached thread when main() exits?, does it mean that the detached thread would automatically terminate when the main exits ?
I need an explanation for this behavior.
When main returns, the process is terminated. If there was a thread running, there are no guarantees that it will have a chance to finish.
Furthermore, technically touching any global state after main has returned results in undefined behaviour because all static storage objects will be destroyed by the main thread.
Basically, std::thread::detach is rarely useful because you simply have to use some other way to join the thread instead. There's no standard way to "wait for all detached threads and then stop". There are platform specific ways though (pthread_exit).
This question already has answers here:
C++ std::vector of independent std::threads
(4 answers)
Closed 4 years ago.
#include <iostream>
#include <thread>
void func() {
std::cout << "Hello";
}
int main() {
std::vector<std::thread> threads;
int n = 100;
for (int i = 0; i < n; i++) {
std::cout << "executing thread" << std::endl;
threads.push_back(std::thread(func));
}
}
My program prints "executing thread" once and it ends. What is the cause?
After this loop completes the destructor of std::vector<std::thread> is invoked. std::thread destructor calls std::terminate if the thread was neither detached nor joined, like in your case.
To fix that, add the following after the loop:
for(auto& thread : threads)
thread.join();
Make sure you join the threads to wait for them all to complete:
for (auto &thread : threads) {
thread.join();
}
If the program continues after this point and doesn't exit immediately, flush the output since it may be buffered:
std::cout << std::flush;
Even if you don't join, it should still print "executing thread" 100 times.
Perhaps the problem is using "endl" instead of "std::endl"
Once the loop creating the threads is done, your program continues. And it continues to leave the main function which causes all variables defined inside the main function to go out of scope and their life-time ending. This leads to the destruction of the objects, including the vector which then leads to all the thread object in the vector being destructed.
And as noted by others, the destruction of a thread object will lead to program termination if the thread is not joined or detached.
While the other answers tell you to join the threads (which IMO is the recommended solution here) there is another possible solution: To detach the threads.
While this will lead to the std::terminate function to be called and prematurely terminate your program, this will lead to another problem, as leaving the main function ends the process and all its threads.
If you for some reason what your threads to continue to live on after the main function exits, you need to detach the threads and exit the "main thread" using an operating-system specific function. This will leave the process running with all your created threads still chugging along.
In the listing bellow, I expect that as I call t.detach() right after the line when the thread is created, the thread t will run in background while the printf("quit the main function now \n") will called and thenmain will exit.
#include <thread>
#include <iostream>
void hello3(int* i)
{
for (int j = 0; j < 100; j++)
{
*i = *i + 1;
printf("From new thread %d \n", *i);
fflush(stdout);
}
char c = getchar();
}
int main()
{
int i;
i = 0;
std::thread t(hello3, &i);
t.detach();
printf("quit the main function now \n");
fflush(stdout);
return 0;
}
However from what it prints out on the screen it is not the case. It prints
From new thread 1
From new thread 2
....
From new thread 99
quit the main function now.
It looks like the main function waits until the thread finishes before it executes the commandprintf("quit the main function now \n"); and exits.
Can you please explain why it is? What I am missing here?
The problem is that your thread is too fast.
It's able to print all 100 strings before main gets a chance to continue.
Try making the thread slower and you'll see the main printf before that of the thread.
It happens, based on your OS scheduling. Moreover the speed of your thread affects the output too. If you stall the thread (change 100 to 500 for example), you will see the message first.
I just executed the code and the "quit the main function now." message appeared first, like this:
quit the main function now
From new thread 1
From new thread 2
From new thread 3
From new thread 4
...
You are right about detach:
Detaches the thread represented by the object from the calling thread, allowing them to execute independently from each other.
but this does not guarantee that the message "quit the main function now" will appear first, although it's very likely.
It looks like the main function waits until the thread finishes before it executes the command printf("quit the main function now \n"); and exits.
That's because when you create a thread, it gets scheduled for execution, but the order of events across threads is no longer sequential, ordered, or deterministic. In some runs of your program, the output of hello3 will occur before quit the main function now, in some runs it'll print afterwards, and in some runs, the output will be interleaved. This is a form of Undefined Behavior normally referred to as a "Race Condition". In most (but not all) cases, the output of hello3 prints last because there's some overhead (varies by the OS and processor) in setting up a thread, so the several microseconds it takes to properly build the thread and ready it for execution takes so long that the printf statement in your main function already had time to execute and flush before the thread was ready to run.
If you want explicit evidence that things are running concurrently, you should add more work into the main thread before the quit statement so that it becomes unlikely that the main function will finish before the thread is ready to start executing.
There are two major problems with your code:
As soon the main function exits, you will have undefined behaviour because the variable i, referenced by the detached thread, no longer exists.
As soon the whole process ends after the main function returns, the detached thread will also die.
I am trying to use multithread for connecting for more then one peer simultinaly.
While I am running my code and run more then a one thread the program crashes in the "connect" function and it writes: "Abort() has been called".
This is How I call to the threads:
TcpPeers(OrderedMap<std::string, unsigned short> peers, std::string infoHash)
{
this->peers = peers;
peersArr = new Peer[peers.GetSize()];
for (int i = 0; i < peers.GetSize(); i++)
{
Peer * pp = new Peer(peers.GetKeyByIndex(i), peers.GetValueByIndex(i), infoHash);
*(peersArr + i) = *pp;
}
for (int i = 0; i < peers.GetSize(); i++)
{
std::thread t1(&Peer::CreateConnection, *(peersArr + i));
}
}
A peer is another client that I need to connect with while I am trying to implement the bittorent protocol.
Again, when there is one thread all goes right, when I have more then two peers all crashes.
When a std::thread object gets destroyed it is not allowed to be joinable(), i.e., one of two things have to happen before it is destroyed:
It was detached and the thread has gone into the wild and there is pretty much no control over whether it has finished or not.
The thread has been join()ed.
If a std::thread object is destroyed without either of these states, std::terminate() is called which is probably the cause for the call to abort() you observe. In your loop you keep destroying threads without having called either detach() or join() on them. The system sees that as a request to terminate your program.
In case you need a reference for this behavior: see 30.3.1.3 [thread.thread.destr] paragraph 1:
~thread();
If joinable(), calls std::terminate(). Otherwise, has 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 ]
struct Test {
bool active{true};
void threadedUpdate() {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if(!active) // crashes here after Test instance is destroyed
return;
}
Test() {
std::thread([this]{ while(true) threadedUpdate(); }).detach();
}
~Test() {
// somehow stop the detached thread?
}
};
When an instance of Test is initialized, it spawns and detaches an std::thread which runs in background. When the same instance is destroyed, the previously mentioned thread tries to access the active member, which was destroyed along with the instance, causing a crash (and an AddressSanitizer backtrace).
Is there a way to stop the detached thread on ~Test()?
The design is bad. How should a thread running in background until the caller is destroyed be spawned/handled correctly?
Make the thread a member of the class, and instead of detaching it in the constructor, join it in the destructor. To stop the thread from looping, you can have a boolean inside the class that signals whether the thread should continue running or not (std::atomic<bool> update).
The thread could be executing this: [this] { while (update) threadUpdate(); }.
In the destructor of your class, do update = false, and call thread.join()
You can't stop detached threads. That's the point of .detach() - you don't have any way to refer to the detached thread anymore, at least as far as the C++ standard specifies. If you want to keep a handle to the thread, store the std::thread and call .join() in the destructor.