Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Most thread systems allow you to send a signal to a thead.</p> <p>Example: pthreads</p> <pre><code>pthread_kill(pthread_t thread, int sig); </code></pre> <p>This will send a signall to a thread. You can use this to kill the thread. Though this can leave a few of the resources hanging in an undefined state.</p> <p>A solution to the resource problem is to install a signall handler.<br> So that when the signal handler is called it throws an exception. This will cause the thread stack to unwind to the entry point where you can then get the thread to check a variable about weather it is sill alive.</p> <p>NOTE: You should never allow an exception to propogate out of a thread (this is so undefined my eyes bleed thinking about it). Basically catch the exception at the thread entry point then check some state variable to see if the thread should really exit.</p> <p>Meanwhile the thread that sends the signal should wait for the thread to die by doing a join.</p> <p>The only issues are that when you throw out of signal handler function you need to be careful. You should not use a signal that is asynchronus (ie one that could have been generated by a signal in another thread). A good one to use is SIGSEGV. If this happens normally then you have accessed invalid memory any you thread should think about exiting anyway!</p> <p>You may also need to specify an extra flag on some systems to cope.<br> <a href="http://software.intel.com/sites/products/documentation/studio/composer/en-us/2009/compiler_c/copts/ccpp_options/option_fnon_call_exceptions.htm" rel="nofollow noreferrer">See This article</a></p> <p>A working example using pthreads:</p> <pre><code>#include &lt;pthread.h&gt; #include &lt;iostream&gt; extern "C" void* startThread(void*); extern "C" void shouldIexit(int sig); class Thread { public: Thread(); virtual ~Thread(); private: friend void* startThread(void*); void start(); virtual void run() = 0; bool running; pthread_t thread; }; // I have seen a lot of implementations use a static class method to do this. // DON'T. It is not portable. This is because the C++ ABI is not defined. // // It currently works on several compilers but will break if these compilers // change the ABI they use. To gurantee this to work you should use a // function that is declared as extern "C" this guarantees that the ABI is // correct for the callback. (Note this is true for all C callback functions) void* startThread(void* data) { Thread* thread = reinterpret_cast&lt;Thread*&gt;(data); thread-&gt;start(); } void shouldIexit(int sig) { // You should not use std::cout in signal handler. // This is for Demo purposes only. std::cout &lt;&lt; "Signal" &lt;&lt; std::endl; signal(sig,shouldIexit); // The default handler would kill the thread. // But by returning you can continue your code where you left off. // Or by throwing you can cause the stack to unwind (if the exception is caught). // If you do not catch the exception it is implementation defined weather the // stack is unwound. throw int(3); // use int for simplicity in demo } Thread::Thread() :running(true) { // Note starting the thread in the constructor means that the thread may // start before the derived classes constructor finishes. This may potentially // be a problem. It is started here to make the code succinct and the derived // class used has no constructor so it does not matter. if (pthread_create(&amp;thread,NULL,startThread,this) != 0) { throw int(5); // use int for simplicity in demo. } } Thread::~Thread() { void* ignore; running = false; pthread_kill(thread,SIGSEGV); // Tell thread it may want to exit. pthread_join(thread,&amp;ignore); // Wait for it to finish. // Do NOT leave before thread has exited. std::cout &lt;&lt; "Thread Object Destroyed" &lt;&lt; std::endl; } void Thread::start() { while(running) { try { this-&gt;run(); } catch(...) {} } std::cout &lt;&lt; "Thread exiting" &lt;&lt; std::endl; } class MyTestThread:public Thread { public: virtual void run() { // Unless the signal causes an exception // this loop will never exit. while(true) { sleep(5); } } }; struct Info { Info() {std::cout &lt;&lt; "Info" &lt;&lt; std::endl;} ~Info() {std::cout &lt;&lt; "Done: The thread Should have exited before this" &lt;&lt; std::endl;} }; int main() { signal(SIGSEGV,shouldIexit); Info info; MyTestThread test; sleep(4); std::cout &lt;&lt; "Exiting About to Exit" &lt;&lt; std::endl; } &gt; ./a.exe Info Exiting About to Exit Signal Thread exiting Thread Object Destroyed Done: The thread Should have exited before this &gt; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    1. COI think that when you use to signal the thread, you immediatly terminate whatever this->run() did, and therefore leaving the Thread's data in undefined state, which is bad (see way 1 ddj.com/architect/207100682). Maybe if you ommit signal from your solution and leave Thread::running flag in thread function (Thread::startup()) along with pthread_join() in d-tor this will solve the problem also as proposed already by some of posters here. In this case you will leave thread function while entering next iteration of while.
      singulars
    2. CO@idimba: You are partially correct. If you do not install a singal handler by default the thread will just terminate. Which is not good and will behave as described in the DDJ article and also my initial comments above. BUT if you define your own signal handler the thread is not auto terminated that is upto the handler. If you look up the code you will see that I install a signal handler that throws an exception. This will cause the stack to unwind correctly (as the exception is caught). As long as you write exception safe RAII code this method is acceptable.
      singulars
    3. COYou're right for RAII code, which is exception safe, this will work. I also like in your solution the fact that the user supplied thread function is not exposed to the implementation details - it just spins :) IMHO, inforcing thread function to use RAII data is not always realistic. Writting exceptioon safe code is even a bigger challange for an avarage programmer. If my comment is incorrect, I'll delete it :)
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload