Files

37 lines
1.4 KiB
C++

#pragma once
#include "camera_pipeline.hpp"
#include <atomic>
#include <csignal>
#include <pthread.h>
#include <stdexcept>
#include <thread>
namespace cms {
// Construct before starting workers so all threads inherit the signal mask.
// Stop requests run in an ordinary thread, never an asynchronous signal handler.
class StopSignals {
public:
explicit StopSignals(CameraPipeline& pipeline):pipeline_(pipeline) {
sigemptyset(&signals_);sigaddset(&signals_,SIGINT);sigaddset(&signals_,SIGTERM);
if(pthread_sigmask(SIG_BLOCK,&signals_,&old_)!=0)throw std::runtime_error("Cannot block termination signals");
try {
thread_=std::thread([this]{
while(!done_) {
timespec timeout{0,100000000};
int signal=sigtimedwait(&signals_,nullptr,&timeout);
if(signal==SIGINT||signal==SIGTERM){pipeline_.requestStop();break;}
}
});
}catch(...){pthread_sigmask(SIG_SETMASK,&old_,nullptr);throw;}
}
~StopSignals(){done_=true;if(thread_.joinable())thread_.join();pthread_sigmask(SIG_SETMASK,&old_,nullptr);}
StopSignals(StopSignals const&)=delete;
StopSignals& operator=(StopSignals const&)=delete;
private:
CameraPipeline& pipeline_;
sigset_t signals_{},old_{};
std::atomic<bool> done_{false};
std::thread thread_;
};
}