How do I terminate a thread in C++11?
Asked Answered
K

8

184

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.

Keldah answered 31/8, 2012 at 1:10 Comment(1)
Here is good question on this topic: https://mcmap.net/q/137537/-c-0x-thread-interruption "All the language specification says that the support isn't built into the language"Dairying
C
167
  1. You could call std::terminate() from any thread and the thread you're referring to will forcefully end.

  2. 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.

  3. 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.

Cailly answered 31/8, 2012 at 1:32 Comment(5)
Slight nitpick on "don't leak intra-process resources": While it is of course true that the OS will reclaim all resources after killing the process, resources are leaked as far as the program is concerned. That is usually irrelevant, but may still be an issue in some cases. std::terminate neither calls static destructors nor does it flush output buffers, so the order in which resources are released isn't well-defined, nor do you have any guarantee that any of your data is visible to the user or written to permanent store, or even consistent and complete.Hindorff
You can also call exit() or abort() to the same overall effect.Chrissy
#1 is a joke and @ChrisDodd is right. The joke is explained in the answer in the first sentence under #3. Also see Nanno Langstraat's answer and the comments below it.Cailly
Doesn't std::terminate() kill the entire program?Underhanded
Yes. Options 1 and 2 don't leak intra-process resources, but they terminate every thread. Somehow it is not as funny when you have to explain the joke... ;-)Cailly
P
64

@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."

Peculiarity answered 12/12, 2013 at 14:53 Comment(3)
Ahh, my #1 is truly funny. You don't have to specify which thread you want to forcefully end. The system just magically knows which one you want to forcefully end and does it!Cailly
Yes, the std::terminate() answer is like a classic mischievous Djinn story; it fulfills everything in the OP's wish to the letter, though probably not in the way he meant. The understated humor made me smile. :-)Peculiarity
Just have to prevent innocent C++ novices from getting their hopes up too far / too long.Peculiarity
C
20

Tips of using OS-dependent function to terminate C++ thread:

  1. 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.

  2. 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.

More explanations please refer to: http://bo-yang.github.io/2017/11/19/cpp-kill-detached-thread .

Chumash answered 20/11, 2017 at 18:18 Comment(2)
No no no! That will not work! See here: stackoverflow.com/a/72387607Horwath
It is undefined behavior to cache the result of std::thread::native_handle(), then perform a detach() and then execute pthread_cancel() on that cached native handle! Because, if the thread happened to (unexpectedly) finish in the meanwhile, pthread_cancel() will be called with a dangling pointer! Instead, just call pthread_cancel() first, and THEN detach() the useless thread.Pedology
A
20

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)
Adapter answered 27/5, 2019 at 14:48 Comment(2)
But what about if the thread is performing a busy blocked job like a curl command (which takes long to execute or something). And this curl command (read libcurl library) is a blocking call in the thread. I don't have a while loop or something to check for stop_thread_1.Friedrich
To answer my own remark. I didn't solve my problem yet, but I think the answer lies in libcurl "multi interface", with the curl_multi_wakeup and curl_multi_poll calls.Friedrich
R
19

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.

Redden answered 19/2, 2015 at 10:39 Comment(7)
This isn't a very helpful answer. Multi-processing isn't relevant here, and the observations about multi-threading are rather broad.Upset
What I wanted to say and said in details is that multithreading model doesn't provide formal way of forceful thread termination. C++ wants to follow the clear models including memory model, multithreading model etc. Method of forceful thread termination is inherently unsafe. If C++ standard committee would be forced to add it to C++, it would be made with next statement "Method terminate() terminates thread execution. Behavior undefined.", which will be sound like "make some magic and (possibly) terminates the thread".Redden
C# has this feature.Virginavirginal
@Derf Skren "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" (c) ZarathustrA "Remarks: Important! The Thread.Abort method should be used with caution. Particularly when you call it to abort a thread other than the current thread, you do not know what code has executed or failed to execute..." (c) Microsoft link: learn.microsoft.com/en-us/dotnet/api/…Redden
@DerfSkren Thread.Abort is just as risky in C# as this method is in C++. It's a bit unfortunate that the only reliable way to hedge against a buggy third party function that goes into infinite loops or waits for something that will never come is to start a new process. I don't think that was thought through very well.Pulsate
@Pulsate it's just as risky or not risky, depending on the situation. Sometimes it's the only option, or the most convenient. I was just pointing out that in any OS it is possible to stop giving a thread CPU time and to deallocate its stack, and it annoys me when we have to sit through a 2 hour lecture on why that's scary and why language designers are oh so wise to prevent us from doing it.Virginavirginal
The most important post on this page.Astronomy
M
2

Maybe TerminateThread? In windows only.

WINBASEAPI WINBOOL WINAPI TerminateThread (HANDLE hThread, DWORD dwExitCode);

https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-terminatethread

Motherwort answered 2/8, 2022 at 8:11 Comment(0)
P
2

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.

Pedology answered 16/1 at 6:10 Comment(0)
L
1

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
Lysis answered 14/2, 2023 at 12:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.