signal的samplecode
一个signal的samplecode, 需要注意的地方是:
- 资源的释放和析构
- 锁的控制
- 资源的清理
- 事务的控制
/* This is signal handler common code */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <iostream> #include <vector> #include <atomic> #include <csignal> #include <thread> volatile std::atomic_bool g_bExitFlag{false}; volatile std::atomic_bool g_bInitFlag{false}; constexpr uint8_t kNumOfThreads = 5; std::vector<std::thread> gThreads; void SignalHandlerThread(void) { int sig = -1; sigset_t sigset; if (sigemptyset(&sigset) != 0) { /* empty the set of signals */ printf("Emptying signal set failed."); return; } if (sigaddset(&sigset, SIGTERM) != 0) { /* add SIGTERM to signal set */ printf("Adding SIGTERM to signal set failed."); return; } if (sigaddset(&sigset, SIGINT) != 0) { /* add SIGINT to signal set */ printf("Adding SIGINT to signal set failed."); return; } /* wait until signal SIGTERM/SIGINT occurs */ while (sig != SIGTERM && sig != SIGINT) { if (0 != sigwait(&sigset, &sig)) { printf("Sigwait() was called with an invalid signal set."); return; } } printf("SignalHandler get the signal(%d)\n", sig); g_bExitFlag = true; } int SetSignalMask() { bool success = true; sigset_t signals; /* Block all signals except SIGABRT, SIGBUS, SIGFPE, SIGILL and SIGSEGV */ success = success && (sigfillset(&signals) == 0); success = success && (sigdelset(&signals, SIGABRT) == 0); success = success && (sigdelset(&signals, SIGBUS) == 0); success = success && (sigdelset(&signals, SIGFPE) == 0); success = success && (sigdelset(&signals, SIGILL)) == 0; success = success && (sigdelset(&signals, SIGSEGV) == 0); success = success && (pthread_sigmask(SIG_SETMASK, &signals, nullptr) == 0); if (!success) { printf("SetSignalMask failed. \n"); return -1; } return 0; } int Init() { /* initialize signal handling */ SetSignalMask(); /* spawn a new signal handler thread */ gThreads.push_back(std::thread(SignalHandlerThread)); g_bInitFlag = true; //printf("tid thtread id :%lu. \n", gThreads.begin()->get_id()); printf("tid native handle :%lu. \n", static_cast<pthread_t>(gThreads.begin()->native_handle())); return 0; } void Shutdown() { /* check state */ /* clean-up */ /* kill/cancel pthread */ /* wait pthread */ printf("Waitfor the threads.\n"); for (std::vector<std::thread>::iterator it = gThreads.begin(); it != gThreads.end(); it++) { it->join(); } std::cout << "Terminating." << std::endl; } int Run() { Init(); while (!g_bExitFlag) { /* Todo:work thread */ } Shutdown(); return 0; } int main() { try { Run(); } catch (std::runtime_error& e) { std::cout << "Runtime error: " << e.what(); } catch (std::logic_error& e) { std::cout << "Logic error: "<< e.what(); } catch (std::exception& e) { std::cout << "Exception: "<< e.what(); } catch (...) { std::cout << "Unknown exception"; } return 0; }
/* like pause() */ void HandleSignals() { sigset_t sigset; int signal = 0; bool done = false; ::sigemptyset(&sigset); ::sigaddset(&sigset, SIGTERM); ::sigaddset(&sigset, SIGINT); while (!done) { timespec timeout; timeout.tv_sec = 1; timeout.tv_nsec = 0; signal = ::sigtimedwait(&sigset, NULL, &timeout); switch (signal) { case SIGINT: printf("call signal SIGINT"); done = true; break; case SIGTERM: printf("call signal SIGTERM"); done = true; break; } } }