Blue Granny
Blue Granny

Reputation: 800

C++ Killing a std::thread

I have a program that creates a thread that listens for an event. There is a situation in which this thread will never receive this event, and I must terminate it. I know how to catch the case in which it will not receive this event.

I've created a std::thread, however I found nothing on how to terminate the thread. I've tried calling

t.detach()

And then letting the destructor so the work, but I cannot clean up resources allocated by the thread this way.

My questions are: 1. Is there a way to send a SIGKILL or equivalent to a std::thread to kill it? And 2. Is there a way to catch this signal from within the thread to clean up resources?

The question asked (and answered) How do I terminate a thread in C++11? doesn't answer my question as I want to terminate the thread from it's parent, not from within the thread.

Furthermore, my problem is that my worker thread can be either waiting for a blocking system call (i.e., an incoming packet) or a conditional variable, which is why this is tricky.

Upvotes: 6

Views: 10019

Answers (4)

eerorika
eerorika

Reputation: 238291

  1. Is there a way to send a SIGKILL or equivalent to a std::thread to kill it?

There is no such equivalent; at least a standard one.

  1. Is there a way to catch this signal from within the thread to clean up resources?

There is no standard way in C++ to signal a thread.

POSIX has pthread_kill that can be used to signal a thread. Note that "stop", "continue", or "terminate" signals affect the entire process, so this is not for what you're asking exactly.

However, asynchronous signal handlers are limited on what they can do, and resource cleanup won't be possible. What you should do is let the thread know that it should terminate, and let it stop and cleanup voluntarily.

thread that listens for an event.

Solution depends on what kind of listening we are considering. If it is a condition variable, you can set an atomic boolean to request termination and wake up the thread by notifying.

If listening is a blocking system call, solution is a bit trickier. The great thing about raising a signal, is that it interrupts blocking system calls. You can use the handler to set a volatile sig_atomic_t variable that the thread can read and voluntarily return. The interruption may give your thread a chance to check the variable before resuming the wait. The caveat is that we must turn that may into a guarantee:

You must register the signal handler using sigaction (standard POSIX function; not standard C++) with SA_RESTART unset. Otherwise depending on system defaults, the system call might resume instead of returning.


Another approach is to send the event that the other thread is waiting for. This may be simpler or trickier than above depending on what kind of event we are considering. For example, when listening on a socket, it is typically possible to connect to that socket.


There is a proposal to introduce std::jthread thread wrapper into a future C++ standard, which offers a portable way to request a thread to stop. Unfortunately, I don't know what guarantees there would be regarding blocking system calls.

Upvotes: 3

João Paulo
João Paulo

Reputation: 6670

You can't kill a thread by standard c++ ways and, generally speaking, it's not a desirable behavior. You can use conditional variables to achieve a similar behavior with a "signal system":

#include <mutex>
#include <thread>
#include <atomic>
#include <iostream>

std::mutex m;
std::condition_variable cv;
std::atomic_bool state;

void worker_thread() {
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, [] { //waits for the notify_one "signal"
        return state.load(); //returns false if the waiting should be continued. 
    });
    std::cout << "Finished waiting..." << std::endl;
}

int main() {
    state.store(false); //set initial state
    std::thread worker(worker_thread);

    std::cout << "Start waiting..." << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(2)); //do some work here
    {
        std::lock_guard<std::mutex> lk(m); //avoids cv to get notified before been in wait state
        state.store(true);
        cv.notify_one(); //emit the signal once "state" var is true
    }

    worker.join();
    return 0;
}

Upvotes: 3

darune
darune

Reputation: 10962

There's no standard way to kill off a thread, but depends on the platform.

On windows, you may use TerminateThread for example.

However, be advised, unless you know of the sides-effects, etc., this is often-times an anti-pattern to do so.

Upvotes: 2

Pawan Adhikari
Pawan Adhikari

Reputation: 69

Generally killing thread is the undesired behaviour, you want to initiate the thread , do the necessary implementation based on the condition, and if the condition don't satisfy then you could exit it cleanly. Probably use std::condition_variable ... and set the condition from main thread so that child could exit based on certain condition.

Upvotes: 2

Related Questions