C ++, signal and streams

I'm having a hard time constructing my application's main workflow using streams and signals.

My goal is to have the main thread, trap signals and other threads doing stuff periodically (actually using sensors on the raspberry pi and storing the extracted data). I need the ability to close the program in a clean way, i.e. Wait for the sensor to finish recording data (if any, when the signal occurs) before closing. I am using C ++ 11.

At the moment I have this example:

#include <iostream>
#include <thread>
#include <csignal>
#include <mutex>

#define NUM_THREAD 3;

static volatile int stop = 0;     // If the threads needs to stop
std::mutex m;                     // Mutex

void threadHandle(int tid) {
    while(1) {
        std::cout << "Launched by thread " << tid << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "I have sleep well " << tid << std::endl;

        m.lock();
        if(stop) {
            std::cout << "Thread " << tid << " needs to stop" << std::endl;
            m.unlock();
            break;
        }
        m.unlock();
    }
}

void signalHandler(int signum) {
    m.lock();
    std::cout << "Signal " << signum << " received" << std::endl;
    stop = 1;
    m.unlock();
}

int main() {
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

     //Launch a group of threads
     for (int i = 0; i < NUM_THREAD; i++) {
         t[i] = std::thread(call_from_thread, i);
     }

     std::cout << "Launched from the main\n";

     for (int i = 0; i < NUM_THREAD; i++) {
         t[i].join();
     }

     return 0;
}

      

My breakpoint value is volatile only because I am using it inside a signal handler. Should I use std :: atomic_int to provide atomic calls to my signal's value? Is a mutex really necessary? Or more generally, is this a good way to achieve what I want?

Another problem I could solve is that some sensors may have latency between very large (e.g. 2 or 3 hours) measurements, so I will need to check the stop value every 2 or 3 seconds .. and this doesn't seem like a clean way to do it. Another solution, sending signals to threads, lets me just put my thread to sleep; but again I have no controls to tell the thread to complete its action before completing.

Thanks in advance!

+3


source to share


2 answers


Mutex operations are not allowed in a signal handler. You can split the variable stop

into two parts:

  • stop_main

    which is set in the signal handler and waits on the main thread. Since the signal handler runs in the context of the main thread, it is sufficient to declare it volatile (or std :: atomic).
  • stop_threads

    which is given in the main thread and others are waiting for it. The most appropriate type for this variable is std :: condition_variable. This type also helps in waiting for a long time.

Something like that:



std::atomic<int> stop_main = 0;
std::condition_variable stop_threads;
std::mutex m; // protects 'stop_threads'

void threadHandle(int tid)
{
    while(1)
    {
        /* .. do something .. */

        std::unique_lock<std::mutex> l(m);
        if(stop_threads.wait_for(l, std::chrono::hours(2)) ==
            std::cv_status::no_timeout) break;
    }
}
void signalHandler(int signum)
{
    stop_main.store(1);
}
int main()
{
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

    for (int i = 0; i < NUM_THREAD; i++) {
        t[i] = std::thread(threadHandle, i);


    while(!stop_main.load())
    {
        /* Some workload may be here */
        sleep(10); // Signals will interrupt this function.
    }

    stop_threads.notify_all();

    for (int i = 0; i < NUM_THREAD; i++) {
        t[i].join();

    return 0;
}

      

I'm not sure if C ++ guarantees that the signal will be sent to the main thread and not others. Otherwise, you need to block signals on other threads.

sleep(10)

in the main thread can be replaced by any function interrupted by signals.

+4


source


A common pattern is to block signals for all worker threads except the special thread used to handle signals.



0


source







All Articles