interrupt_signals.cpp 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include "interrupt_signals.h"
  2. #include <util/generic/yexception.h>
  3. #include <csignal>
  4. static void (*InterruptSignalsHandler)(int signum) = nullptr;
  5. #ifdef _win_
  6. #include <windows.h>
  7. static BOOL WINAPI WindowsSignalsHandler(_In_ DWORD dwCtrlType) {
  8. if (!InterruptSignalsHandler) {
  9. return FALSE;
  10. }
  11. switch (dwCtrlType) {
  12. case CTRL_C_EVENT:
  13. InterruptSignalsHandler(SIGINT);
  14. return TRUE;
  15. case CTRL_BREAK_EVENT:
  16. InterruptSignalsHandler(SIGTERM);
  17. return TRUE;
  18. case CTRL_CLOSE_EVENT:
  19. InterruptSignalsHandler(SIGHUP);
  20. return TRUE;
  21. default:
  22. return FALSE;
  23. }
  24. Y_UNREACHABLE();
  25. }
  26. #endif
  27. // separate function is to enforce 'extern "C"' linkage
  28. extern "C" void CppSignalsHandler(int signum) {
  29. if (InterruptSignalsHandler) {
  30. InterruptSignalsHandler(signum);
  31. }
  32. }
  33. void SetInterruptSignalsHandler(void (*handler)(int signum)) {
  34. InterruptSignalsHandler = handler;
  35. #ifdef _win_
  36. if (!SetConsoleCtrlHandler(WindowsSignalsHandler, TRUE)) {
  37. ythrow TSystemError() << "SetConsoleCtrlHandler failed: " << LastSystemErrorText();
  38. }
  39. for (int signum : {SIGINT, SIGTERM}) {
  40. #else
  41. for (int signum : {SIGINT, SIGTERM, SIGHUP}) {
  42. #endif
  43. if (std::signal(signum, CppSignalsHandler) == SIG_ERR) {
  44. ythrow TSystemError() << "std::signal failed to set handler for signal with id " << signum;
  45. }
  46. }
  47. }