2

I know that this question has been asked and answered many times and I know that the best way to end a thread is to use flags and exit the thread function when it is requested. This is also what I am doing at the moment, but my problem is that the thread function runs for a very Long time, so sometimes I need to wait for several hours until the thread ends. My thread function looks something like this:

void threadfunction()
{
    while(!exitRequested)
    {
        doSomeWork();
        object1.doSomeWork();
        object2.doSomeWork();
        while(somecondition)
        {
            object3.doSomeWork();
        }
        object4.doSomeWork();
    }
}

This is just an example and in reality the code looks much more complex. But what I wanted to demonstrate is that I call several class methods which can take some hours to complete (per function).

So what I'm doing at the moment is to check if exit was requested between the functions (e.g. between object1.doSomeWork(); and object2.doSomeWork();) but as I said a function call can take up to several hours, so I need to check if exit was requested whithin those functions. In order to do this I need to pass the exitRequested flag to those functions, but in my opinion this doesn't look very nice and there could be a better solution for this.

One solution I could think of is by throwing exceptions, to create something like this:

void threadfunction()
{
    try {
        while(!exitRequested)
        {
            ...
        }
    } catch (const ExitRequestException &e) {}
}

But then the exception needs to be raised somehow. As far as I know I can't raise an exception in a thread from another thread, right?

Do you have any better Solutions? Or do you think I really need to pass the exitRequested flag to all those functions and pollute my code?

Thomas Sparber
  • 2,827
  • 2
  • 18
  • 34
  • possible duplicate of [How do I terminate a thread in C++11?](http://stackoverflow.com/questions/12207684/how-do-i-terminate-a-thread-in-c11) – merlin2011 Aug 28 '15 at 07:27
  • You could pass a reference (maybe via a `shared_ptr`) to the exit flag to each of the various work objects in their constructor. – Jonathan Potter Aug 28 '15 at 07:31
  • Pass the exitRequested flag (by reference!) to the functions. – Werner Henze Aug 28 '15 at 07:33
  • 1
    @Jonathan Yeah you're right, I also thought about this. But if I do it I again have *polluted* my code with Exit requests which are not needed for the actual execution. I'm just wondering if there is a better solution. – Thomas Sparber Aug 28 '15 at 07:33
  • Just break down the function into checkpoints/chunks/stages or whatever you call it. – Non-maskable Interrupt Aug 28 '15 at 07:35

1 Answers1

1

After googling around for a while I found (and created) an answer which is perfectly fine for me, although it only works for pthreads. For non pthreads I can immagine using the concept which is described here.

So what am I doing now: I am sending a signal to the worker thread. This thread handles the custom signal in a signal handler and raises an exception. This exception is cought in the outer part of the thread function. By using this concept I have the advantage that an exception is thrown and the stack is unwound, so I can close all open resources. Here is my complete working example:

#include <thread>
#include <signal.h>
#include <unistd.h>
#include <iostream>

using namespace std;

//Custom exception which is used to stop the thread
class StopException {};

void sig_fun(int s)
{
    if(s == SIGUSR2)throw StopException();
}

void threadFunction()
{
    cout<<"Thread started"<<endl;
    try {
        while(true)
        {
            //Work forever...
            sleep(1);
        }
    } catch(const StopException &e) {
        cout<<"Thread interrupted"<<endl;
    }
    cout<<"Thread stopped"<<endl;
}

int main(int argc, char *args[])
{
    //Install Signal handler function
    signal(SIGUSR2, sig_fun);
    pthread_t threadObject;
    thread t([&threadObject]()
    {
        //Store pthread_t object to be able to use it later
        threadObject = pthread_self();
        threadFunction();
    });

    string temp;
    cout<<"Write something when you want the thread to be killed"<<endl;
    cin>>temp;

    //Send Signal to thread
    pthread_kill(threadObject, SIGUSR2);
    t.join();
}
Thomas Sparber
  • 2,827
  • 2
  • 18
  • 34
  • I'm pretty sure, throwing an exception in a signal handler is undefoned behavior unless your compiler specifically allows it. And even then, you could not use any function that is marked as noexcept. – MikeMB Aug 28 '15 at 09:05
  • @MikeMB: Thank you very much for the great comment! I didn't hink of this! But according to this (http://www.ibm.com/developerworks/library/l-cppexcep/) article it should work. – Thomas Sparber Aug 28 '15 at 09:19
  • 1
    That article is from 2005, it predates c++11 (noexcept and standard multithreading in particular) and was probably written under the asumption of a specific exception handling mechanism (there are different ones). Also the article only mentiones synchonous signals, meaning, signals that where raised within the thread in which you handle them, meaning as a result of some action (like floating point exception or segmentation fault). However, you try to use an asynchronous signals / exceptions. – MikeMB Aug 28 '15 at 09:46
  • 1
    Again, if your compiler documentation states, that throwing an exception from a signal handler is fine then it might work for your particular system/compiler, but I can almost guarantee you, that this is not ISO-C++ standard conformant. The only interaction between signal handler and program that the C++ standard allows inside a signal handler is to use a `std::atomic` or `volatile std::sig_atomic_t` [variable or exit the program](http://en.cppreference.com/w/cpp/utility/program/signal). POSIX allows much more, but doesn't mention exceptions, as they are a c++ mechanism. – MikeMB Aug 28 '15 at 09:54
  • Thank you MikeMB, I understand – Thomas Sparber Aug 28 '15 at 09:55