SignalHandler.h 3.2 KB

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