Reputation: 8718
I don't need to terminate the thread correctly, or make it respond to a "terminate" command. I am interested in terminating the thread forcefully using pure C++11.
Upvotes: 195
Views: 370642
Reputation: 136515
I don't need to terminate the thread correctly, or make it respond to a "terminate" command. I am interested in terminating the thread forcefully using pure C++11.
You cannot terminate a thread forcefully and expect your process address space to remain consistent and be able to continue executing normally after that.
Forcefully terminating a thread doesn't unlock spinlocks or mutexes it may had acquired while invoking stdio
or malloc
functions when you terminated it, for an easy example, so that other threads in your process deadlock or fail calling those after that.
In other words, terminating a thread forcefully may create more problems than it tries solves. std::quick_exit doesn't create more problems.
Running rogue/untrusted threads in a separate child process is a robust solution - terminating a child process doesn't risk corrupting or destabilizing your process.
Upvotes: 1
Reputation: 717
Tips of using OS-dependent function to terminate C++ thread:
std::thread::native_handle()
only can get the thread’s valid native handle type before calling join()
or detach()
. After that, native_handle()
returns 0 - pthread_cancel()
will coredump.
To effectively call native thread termination function(e.g. pthread_cancel()
), you need to save the native handle before calling std::thread::join()
or std::thread::detach()
. So that your native terminator always has a valid native handle to use.
Upvotes: 23
Reputation: 851
Context analysis touches the question of design measures: How to properly handle Termination of a Thread.
The regular context of thread termination using the thread's functional interface is that the thread cannot end in a way foreseen by design, see e.g. halting problem in a complex or distributed system.
C++11 sadly comes with a functional approach for threads, a thread routine, which suggests to put attributes/states of the executed thread onto the thread's stack. By suspending or terminating a thread those attributes, specialy dangling structures which might be the cause for the thread not being able to end normally, get out of reach and in the best case produce memory leaks.
Otherwise, a Java approach is using a pair of Runnable
and Thread
, where (the implementation of) the Runnable carries the attributes and the Thread instance manages stack and control flow. In a strict workshare the Thread may be killed any time and the attributes still are accessible, may even be repaired and the Runnable may be attached to a new Thread instance to continue work.
The emulation in C++ is reached by passing such Runnable object to the thread routine and
the design rule to have all associated application relevant data inside the Runnable.
Upvotes: 2
Reputation: 2984
C++20 introduced std::jthread
, which internally maintains a stop flag, that can be polled by the thread function to exit itself upon request. But this won't work, if one needs to force stop a thread, that is hanging in a slow system or library call, or, even worse, in a deadlock or similar problem.
On Posix systems, including Linux, Android, iOS and MacOS, force terminating a std::thread
or std::jthread
can be achieved via this C call to the system's threading library:
pthread_cancel(thread.native_handle());
The equivalent call on Windows is:
TerminateThread(thread.native_handle(), 1);
It is safe to call pthread_cancel()
even, if the thread has incidentally just terminated itself before that call: Is it safe to call pthread_cancel() on terminated thread? . However, thread.detach()
or thread.join()
must be called after the cancellation request has been issued. Otherwise, race conditions leading to uncontrolled crashes may occur.
Generally, cancelling a thread is extremely hard to perform safely. Most likely, some resources, including memory, locked mutexes and/or open file descriptors, will not be released correctly. Furthermore, threads hanging in an infinite code loop, are generally not cancelable via pthread_cancel()
, as the cancel is by default deferred to the next call of a system function, that is also a cancellation point. This later behavior can be changed via pthread_setcanceltype()
, but it is almost certain, that doing so leads to even more resource leaks, including the risk of leaving the memory management functions (malloc()
, new
etc.) in a corrupted state.
Nonetheless, especially during application teardown, cancelling blocked threads often can lead to more clean results than calling std::terminate()
, which terminates all threads immediately and doesn't care about destructors of global objects or similar.
Upvotes: 9
Reputation: 1160
You can't use a C++ std::thread
destructor to terminate a single thread in a multi-threads program. Here's the relevant code snippet of std::thread
destructor, located in the thread
header file (Visual C++):
~thread()
{
if (joinable())
std::terminate();
}
If you call the destructor of a joinable thread, the destructor calls std::terminate() that acts on the process; not on the thread, otherwise, it does nothing.
It is possible to "terminating the thread forcefully" (C++11 std::thread) by using OS function. On Windows, you can use TerminateThread. "TerminateThread
is a dangerous function that should only be used in the most extreme cases." - Microsoft | Learn.
TerminateThread(tr.native_handle(), 1);
In order to TerminateThread
to effect, you should not call join()
/ detach()
before, since such a call will nullify native_handle()
.
You should call detach()
(or join()
) after TerminateThread
. Otherwise, as written on the 1st paragraph, on thread destructor std::terminate()
will be called and the whole process will be terminated.
Example:
#include <iostream>
#include <thread>
#include <Windows.h>
void Work10Seconds()
{
std::cout << "Work10Seconds - entered\n";
for (uint8_t i = 0; i < 20; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "Work10Seconds - working\n";
}
std::cout << "Work10Seconds - exited\n";
}
int main() {
std::cout << "main - started\n";
std::thread tr{};
std::cout << "main - Run 10 seconds work thread\n";
tr = std::thread(Work10Seconds);
std::cout << "main - Sleep 2 seconds\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "main - TerminateThread\n";
TerminateThread(tr.native_handle(), 1);
tr.detach(); // After TerminateThread
std::cout << "main - Sleep 2 seconds\n";
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "main - exited\n";
}
Output:
main - started
main - Run 10 seconds work thread
main - Sleep 2 seconds
Work10Seconds - entered
Work10Seconds - working
Work10Seconds - working
Work10Seconds - working
main - TerminateThread
main - Sleep 2 seconds
main - exited
Upvotes: 2
Reputation: 184
Maybe TerminateThread? In windows only.
WINBASEAPI WINBOOL WINAPI TerminateThread (HANDLE hThread, DWORD dwExitCode);
Upvotes: 4
Reputation: 1395
@Howard Hinnant's answer is both correct and comprehensive. But it might be misunderstood if it's read too quickly, because std::terminate()
(whole process) happens to have the same name as the "terminating" that @Alexander V had in mind (1 thread).
Summary: "terminate 1 thread + forcefully (target thread doesn't cooperate) + pure C++11 = No way."
Upvotes: 65
Reputation: 592
I guess the thread that needs to be killed is either in any kind of waiting mode, or doing some heavy job. I would suggest using a "naive" way.
Define some global boolean:
std::atomic_bool stop_thread_1 = false;
Put the following code (or similar) in several key points, in a way that it will cause all functions in the call stack to return until the thread naturally ends:
if (stop_thread_1)
return;
Then to stop the thread from another (main) thread:
stop_thread_1 = true;
thread1.join ();
stop_thread_1 = false; //(for next time. this can be when starting the thread instead)
Upvotes: 23
Reputation: 3640
This question actually have more deep nature and good understanding of the multithreading concepts in general will provide you insight about this topic. In fact there is no any language or any operating system which provide you facilities for asynchronous abruptly thread termination without warning to not use them. And all these execution environments strongly advise developer or even require build multithreading applications on the base of cooperative or synchronous thread termination. The reason for this common decisions and advices is that all they are built on the base of the same general multithreading model.
Let's compare multiprocessing and multithreading concepts to better understand advantages and limitations of the second one.
Multiprocessing assumes splitting of the entire execution environment into set of completely isolated processes controlled by the operating system. Process incorporates and isolates execution environment state including local memory of the process and data inside it and all system resources like files, sockets, synchronization objects. Isolation is a critically important characteristic of the process, because it limits the faults propagation by the process borders. In other words, no one process can affects the consistency of any another process in the system. The same is true for the process behaviour but in the less restricted and more blur way. In such environment any process can be killed in any "arbitrary" moment, because firstly each process is isolated, secondly, operating system have full knowledges about all resources used by process and can release all of them without leaking, and finally process will be killed by OS not really in arbitrary moment, but in the number of well defined points where the state of the process is well known.
In contrast, multithreading assumes running multiple threads in the same process. But all this threads are share the same isolation box and there is no any operating system control of the internal state of the process. As a result any thread is able to change global process state as well as corrupt it. At the same moment the points in which the state of the thread is well known to be safe to kill a thread completely depends on the application logic and are not known neither for operating system nor for programming language runtime. As a result thread termination at the arbitrary moment means killing it at arbitrary point of its execution path and can easily lead to the process-wide data corruption, memory and handles leakage, threads leakage and spinlocks and other intra-process synchronization primitives leaved in the closed state preventing other threads in doing progress.
Due to this the common approach is to force developers to implement synchronous or cooperative thread termination, where the one thread can request other thread termination and other thread in well-defined point can check this request and start the shutdown procedure from the well-defined state with releasing of all global system-wide resources and local process-wide resources in the safe and consistent way.
Upvotes: 21
Reputation: 219488
You could call std::terminate()
from any thread and the thread you're referring to will forcefully end.
You could arrange for ~thread()
to be executed on the object of the target thread, without a intervening join()
nor detach()
on that object. This will have the same effect as option 1.
You could design an exception which has a destructor which throws an exception. And then arrange for the target thread to throw this exception when it is to be forcefully terminated. The tricky part on this one is getting the target thread to throw this exception.
Options 1 and 2 don't leak intra-process resources, but they terminate every thread.
Option 3 will probably leak resources, but is partially cooperative in that the target thread has to agree to throw the exception.
There is no portable way in C++11 (that I'm aware of) to non-cooperatively kill a single thread in a multi-thread program (i.e. without killing all threads). There was no motivation to design such a feature.
A std::thread
may have this member function:
native_handle_type native_handle();
You might be able to use this to call an OS-dependent function to do what you want. For example on Apple's OS's, this function exists and native_handle_type
is a pthread_t
. If you are successful, you are likely to leak resources.
Upvotes: 173