signals.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "signals.h"
  2. #include "utils.h"
  3. #include <yql/essentials/utils/backtrace/backtrace.h>
  4. #include <util/stream/output.h>
  5. #include <util/generic/yexception.h>
  6. #include <util/datetime/base.h>
  7. #include <util/network/socket.h>
  8. #include <util/system/getpid.h>
  9. #ifdef _linux_
  10. # include <sys/prctl.h>
  11. #endif
  12. #include <string.h>
  13. #include <signal.h>
  14. #include <errno.h>
  15. #include <stdlib.h>
  16. namespace NYql {
  17. volatile sig_atomic_t NeedTerminate = 0;
  18. volatile sig_atomic_t NeedQuit = 0;
  19. volatile sig_atomic_t NeedReconfigure = 0;
  20. volatile sig_atomic_t NeedReopenLog = 0;
  21. volatile sig_atomic_t NeedReapZombies = 0;
  22. volatile sig_atomic_t NeedInterrupt = 0;
  23. volatile sig_atomic_t CatchInterrupt = 0;
  24. TPipe SignalPipeW;
  25. TPipe SignalPipeR;
  26. namespace {
  27. void SignalHandler(int signo)
  28. {
  29. switch (signo) {
  30. case SIGTERM:
  31. NeedTerminate = 1;
  32. break;
  33. case SIGQUIT:
  34. NeedQuit = 1;
  35. break;
  36. #ifdef _unix_
  37. case SIGHUP:
  38. NeedReconfigure = 1;
  39. break;
  40. case SIGUSR1:
  41. NeedReopenLog = 1;
  42. break;
  43. case SIGCHLD:
  44. NeedReapZombies = 1;
  45. break;
  46. #endif
  47. case SIGINT:
  48. if (CatchInterrupt) {
  49. NeedInterrupt = 1;
  50. } else {
  51. fprintf(stderr, "%s (pid=%d) captured SIGINT\n",
  52. GetProcTitle(), getpid());
  53. signal(signo, SIG_DFL);
  54. raise(signo);
  55. }
  56. break;
  57. default:
  58. break;
  59. }
  60. }
  61. void SignalHandlerWithSelfPipe(int signo)
  62. {
  63. SignalHandler(signo);
  64. int savedErrno = errno;
  65. if (write(SignalPipeW.GetHandle(), "x", 1) == -1 && errno != EAGAIN) {
  66. static TStringBuf msg("cannot write to signal pipe");
  67. #ifndef STDERR_FILENO
  68. #define STDERR_FILENO 2
  69. #endif
  70. write(STDERR_FILENO, msg.data(), msg.size());
  71. abort();
  72. }
  73. errno = savedErrno;
  74. }
  75. #ifndef _unix_
  76. const char* strsignal(int signo)
  77. {
  78. switch (signo) {
  79. case SIGTERM: return "SIGTERM";
  80. case SIGINT: return "SIGINT";
  81. case SIGQUIT: return "SIGQUIT";
  82. default:
  83. return "UNKNOWN";
  84. }
  85. }
  86. #endif
  87. #ifdef _unix_
  88. int SetSignalHandler(int signo, void (*handler)(int))
  89. {
  90. struct sigaction sa;
  91. sa.sa_flags = SA_RESTART;
  92. sa.sa_handler = handler;
  93. sigemptyset(&sa.sa_mask);
  94. return sigaction(signo, &sa, nullptr);
  95. }
  96. #else
  97. int SetSignalHandler(int signo, void (*handler)(int))
  98. {
  99. return (signal(signo, handler) == SIG_ERR) ? -1 : 0;
  100. }
  101. #endif
  102. struct TSignalHandlerDesc
  103. {
  104. int signo;
  105. void (*handler)(int);
  106. };
  107. void SetSignalHandlers(const TSignalHandlerDesc* handlerDescs)
  108. {
  109. sigset_t interestedSignals;
  110. SigEmptySet(&interestedSignals);
  111. for (int i = 0; handlerDescs[i].signo != -1; i++) {
  112. int signo = handlerDescs[i].signo;
  113. SigAddSet(&interestedSignals, signo);
  114. if (SetSignalHandler(signo, handlerDescs[i].handler) == -1) {
  115. ythrow TSystemError() << "Cannot set handler for signal "
  116. << strsignal(signo);
  117. }
  118. }
  119. if (SigProcMask(SIG_BLOCK, &interestedSignals, NULL) == -1) {
  120. ythrow TSystemError() << "Cannot set sigprocmask";
  121. }
  122. NYql::NBacktrace::RegisterKikimrFatalActions();
  123. }
  124. } // namespace
  125. void InitSignals()
  126. {
  127. TSignalHandlerDesc handlerDescs[] = {
  128. { SIGTERM, SignalHandler },
  129. { SIGINT, SignalHandler },
  130. { SIGQUIT, SignalHandler },
  131. #ifdef _unix_
  132. { SIGPIPE, SIG_IGN },
  133. { SIGHUP, SignalHandler },
  134. { SIGUSR1, SignalHandler },
  135. { SIGCHLD, SignalHandler },
  136. #endif
  137. { -1, nullptr }
  138. };
  139. SetSignalHandlers(handlerDescs);
  140. }
  141. void InitSignalsWithSelfPipe()
  142. {
  143. TSignalHandlerDesc handlerDescs[] = {
  144. { SIGTERM, SignalHandlerWithSelfPipe },
  145. { SIGINT, SignalHandlerWithSelfPipe },
  146. { SIGQUIT, SignalHandlerWithSelfPipe },
  147. #ifdef _unix_
  148. { SIGPIPE, SIG_IGN },
  149. { SIGHUP, SignalHandlerWithSelfPipe },
  150. { SIGUSR1, SignalHandlerWithSelfPipe },
  151. { SIGCHLD, SignalHandlerWithSelfPipe },
  152. #endif
  153. { -1, nullptr }
  154. };
  155. TPipe::Pipe(SignalPipeR, SignalPipeW);
  156. SetNonBlock(SignalPipeR.GetHandle());
  157. SetNonBlock(SignalPipeW.GetHandle());
  158. SetSignalHandlers(handlerDescs);
  159. }
  160. void CatchInterruptSignal(bool doCatch) {
  161. CatchInterrupt = doCatch;
  162. }
  163. void SigSuspend(const sigset_t* mask)
  164. {
  165. #ifdef _unix_
  166. sigsuspend(mask);
  167. #else
  168. Y_UNUSED(mask);
  169. Sleep(TDuration::Seconds(1));
  170. #endif
  171. }
  172. void AllowAnySignals()
  173. {
  174. sigset_t blockMask;
  175. SigEmptySet(&blockMask);
  176. if (SigProcMask(SIG_SETMASK, &blockMask, NULL) == -1) {
  177. ythrow TSystemError() << "Cannot set sigprocmask";
  178. }
  179. }
  180. bool HasPendingQuitOrTerm() {
  181. #ifdef _unix_
  182. sigset_t signals;
  183. SigEmptySet(&signals);
  184. if (sigpending(&signals)) {
  185. ythrow TSystemError() << "Error in sigpending";
  186. }
  187. return (SigIsMember(&signals, SIGQUIT) == 1) || (SigIsMember(&signals, SIGTERM) == 1);
  188. #else
  189. return false;
  190. #endif
  191. }
  192. } // namespace NYql