SignalHandler.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //
  2. // SignalHandler.h
  3. //
  4. // Library: Foundation
  5. // Package: Threading
  6. // Module: SignalHandler
  7. //
  8. // Definition of the SignalHandler class.
  9. //
  10. // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
  11. // and Contributors.
  12. //
  13. // SPDX-License-Identifier: BSL-1.0
  14. //
  15. #ifndef Foundation_SignalHandler_INCLUDED
  16. #define Foundation_SignalHandler_INCLUDED
  17. #include "Poco/Foundation.h"
  18. #if defined(POCO_OS_FAMILY_UNIX) && !defined(POCO_VXWORKS)
  19. #include <vector>
  20. #include <setjmp.h>
  21. namespace Poco {
  22. class Foundation_API SignalHandler
  23. /// This helper class simplifies the handling of POSIX signals.
  24. ///
  25. /// The class provides a signal handler (installed with
  26. /// installHandlers()) that translates certain POSIX
  27. /// signals (SIGILL, SIGBUS, SIGSEGV, SIGSYS) into
  28. /// C++ exceptions.
  29. ///
  30. /// Internally, a stack of sigjmp_buf structs is maintained for
  31. /// each thread. The constructor pushes a new sigjmp_buf onto
  32. /// the current thread's stack. The destructor pops the sigjmp_buf
  33. /// from the stack.
  34. ///
  35. /// The poco_throw_on_signal macro creates an instance of SignalHandler
  36. /// on the stack, which results in a new sigjmp_buf being created.
  37. /// The sigjmp_buf is then set-up with sigsetjmp().
  38. ///
  39. /// The handleSignal() method, which is invoked when a signal arrives,
  40. /// checks if a sigjmp_buf is available for the current thread.
  41. /// If so, siglongjmp() is used to jump out of the signal handler.
  42. ///
  43. /// Typical usage is as follows:
  44. ///
  45. /// try
  46. /// {
  47. /// poco_throw_on_signal;
  48. /// ...
  49. /// }
  50. /// catch (Poco::SignalException&)
  51. /// {
  52. /// ...
  53. /// }
  54. ///
  55. /// The best way to deal with a SignalException is to log as much context
  56. /// information as possible, to aid in debugging, and then to exit.
  57. ///
  58. /// The SignalHandler can be disabled globally by compiling POCO and client
  59. /// code with the POCO_NO_SIGNAL_HANDLER macro defined.
  60. {
  61. public:
  62. SignalHandler();
  63. /// Creates the SignalHandler.
  64. ~SignalHandler();
  65. /// Destroys the SignalHandler.
  66. sigjmp_buf& jumpBuffer();
  67. /// Returns the top-most sigjmp_buf for the current thread.
  68. static void throwSignalException(int sig);
  69. /// Throws a SignalException with a textual description
  70. /// of the given signal as argument.
  71. static void install();
  72. /// Installs signal handlers for SIGILL, SIGBUS, SIGSEGV
  73. /// and SIGSYS.
  74. protected:
  75. static void handleSignal(int sig);
  76. /// The actual signal handler.
  77. struct JumpBuffer
  78. /// sigjmp_buf cannot be used to instantiate a std::vector,
  79. /// so we provide a wrapper struct.
  80. {
  81. sigjmp_buf buf;
  82. };
  83. typedef std::vector<JumpBuffer> JumpBufferVec;
  84. static JumpBufferVec& jumpBufferVec();
  85. /// Returns the JumpBufferVec for the current thread.
  86. private:
  87. static JumpBufferVec _jumpBufferVec;
  88. friend class ThreadImpl;
  89. };
  90. #ifndef POCO_NO_SIGNAL_HANDLER
  91. #define poco_throw_on_signal \
  92. Poco::SignalHandler _poco_signalHandler; \
  93. int _poco_signal = sigsetjmp(_poco_signalHandler.jumpBuffer(), 1); \
  94. if (_poco_signal) _poco_signalHandler.throwSignalException(_poco_signal);
  95. #else
  96. #define poco_throw_on_signal
  97. #endif
  98. } // namespace Poco
  99. #endif // POCO_OS_FAMILY_UNIX
  100. #endif // Foundation_SignalHandler_INCLUDED