ossig.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // ossig.h - written and placed in the public domain by Jeffrey Walton
  2. //
  3. /// \file ossig.h
  4. /// \brief Utility class for trapping OS signals.
  5. /// \since Crypto++ 5.6.5
  6. #ifndef CRYPTOPP_OS_SIGNAL_H
  7. #define CRYPTOPP_OS_SIGNAL_H
  8. #include "config.h"
  9. #if defined(UNIX_SIGNALS_AVAILABLE)
  10. # include <signal.h>
  11. #endif
  12. NAMESPACE_BEGIN(CryptoPP)
  13. // ************** Unix and Linux compatibles ***************
  14. #if defined(UNIX_SIGNALS_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
  15. /// \brief Signal handler function pointer
  16. /// \details SignalHandlerFn is provided as a stand alone function pointer with external "C" linkage
  17. /// \sa SignalHandler, NullSignalHandler
  18. extern "C" {
  19. typedef void (*SignalHandlerFn) (int);
  20. }
  21. /// \brief Null signal handler function
  22. /// \param unused the signal number
  23. /// \details NullSignalHandler is provided as a stand alone function with external "C" linkage
  24. /// and not a static member function due to the member function's implicit
  25. /// external "C++" linkage.
  26. /// \sa SignalHandler, SignalHandlerFn
  27. extern "C" {
  28. inline void NullSignalHandler(int unused) {CRYPTOPP_UNUSED(unused);}
  29. }
  30. /// Signal handler for Linux and Unix compatibles
  31. /// \tparam S Signal number
  32. /// \tparam O Flag indicating if an existing handler should be overwritten
  33. /// \details SignalHandler() can be used to install a signal handler with the signature
  34. /// <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
  35. /// the sigaction is set to the function and the sigaction flags is set to the flags.
  36. /// If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
  37. /// using sigaction flags set to 0. The default handler only returns from the call.
  38. /// \details Upon destruction the previous signal handler is restored if the former signal handler
  39. /// was replaced.
  40. /// \details On Cygwin systems using Newlib, you should define <tt>_XOPEN_SOURCE=700</tt> or
  41. /// <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
  42. /// you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
  43. /// <tt>_XOPEN_SOURCE=700</tt>.
  44. /// \warning Do not use SignalHandler in a code block that uses <tt>setjmp</tt> or <tt>longjmp</tt>
  45. /// because the destructor may not run.
  46. /// \since Crypto++ 5.6.5
  47. /// \sa NullSignalHandler, SignalHandlerFn, \ref CRYPTOPP_ASSERT "CRYPTOPP_ASSERT", DebugTrapHandler
  48. template <int S, bool O=false>
  49. struct SignalHandler
  50. {
  51. /// \brief Construct a signal handler
  52. /// \param pfn Pointer to a signal handler function
  53. /// \param flags Flags to use with the signal handler
  54. /// \details SignalHandler() installs a signal handler with the signature
  55. /// <tt>void handler_fn(int)</tt>. If <tt>SignalHandlerFn</tt> is not <tt>NULL</tt>, then
  56. /// the sigaction is set to the function and the sigaction flags is set to the flags.
  57. /// If <tt>SignalHandlerFn</tt> is <tt>NULL</tt>, then a default handler is installed
  58. /// using sigaction flags set to 0. The default handler only returns from the call.
  59. /// \details Upon destruction the previous signal handler is restored if the former signal handler
  60. /// was overwritten.
  61. /// \details On Cygwin systems using Newlib, you should define <tt>_XOPEN_SOURCE=700</tt> or
  62. /// <tt>_GNU_SOURCE</tt>; or use <tt>-std=gnu++03</tt>, <tt>-std=gnu++11</tt>, or similar. If
  63. /// you compile with <tt>-std=c++03</tt>, <tt>-std=c++11</tt> or similar, then define
  64. /// <tt>_XOPEN_SOURCE=700</tt>.
  65. /// \warning Do not use SignalHandler in a code block that uses <tt>setjmp</tt> or <tt>longjmp</tt>
  66. /// because the destructor may not run. <tt>setjmp</tt> is why cpu.cpp does not use SignalHandler
  67. /// during CPU feature testing.
  68. /// \since Crypto++ 5.6.5
  69. SignalHandler(SignalHandlerFn pfn = NULLPTR, int flags = 0) : m_installed(false)
  70. {
  71. // http://pubs.opengroup.org/onlinepubs/007908799/xsh/sigaction.html
  72. struct sigaction new_handler;
  73. do
  74. {
  75. int ret = 0;
  76. ret = sigaction (S, 0, &m_old);
  77. if (ret != 0) break; // Failed
  78. // Don't step on another's handler if Overwrite=false
  79. if (m_old.sa_handler != 0 && !O) break;
  80. // Cygwin/Newlib requires -D_XOPEN_SOURCE=700
  81. ret = sigemptyset (&new_handler.sa_mask);
  82. if (ret != 0) break; // Failed
  83. new_handler.sa_handler = (pfn ? pfn : &NullSignalHandler);
  84. new_handler.sa_flags = (pfn ? flags : 0);
  85. // Install it
  86. ret = sigaction (S, &new_handler, 0);
  87. if (ret != 0) break; // Failed
  88. m_installed = true;
  89. } while(0);
  90. }
  91. ~SignalHandler()
  92. {
  93. if (m_installed)
  94. sigaction (S, &m_old, 0);
  95. }
  96. private:
  97. struct sigaction m_old;
  98. bool m_installed;
  99. private:
  100. // Not copyable
  101. SignalHandler(const SignalHandler &);
  102. void operator=(const SignalHandler &);
  103. };
  104. #endif
  105. NAMESPACE_END
  106. #endif // CRYPTOPP_OS_SIGNAL_H