SignalHandler.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Copyright: JessMA Open Source (ldcsaa@gmail.com)
  3. *
  4. * Author : Bruce Liang
  5. * Website : https://github.com/ldcsaa
  6. * Project : https://github.com/ldcsaa/HP-Socket
  7. * Blog : http://www.cnblogs.com/ldcsaa
  8. * Wiki : http://www.oschina.net/p/hp-socket
  9. * QQ Group : 44636872, 75375912
  10. *
  11. * Licensed under the Apache License, Version 2.0 (the "License");
  12. * you may not use this file except in compliance with the License.
  13. * You may obtain a copy of the License at
  14. *
  15. * http://www.apache.org/licenses/LICENSE-2.0
  16. *
  17. * Unless required by applicable law or agreed to in writing, software
  18. * distributed under the License is distributed on an "AS IS" BASIS,
  19. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  20. * See the License for the specific language governing permissions and
  21. * limitations under the License.
  22. */
  23. #pragma once
  24. #include "hpsocket/GlobalDef.h"
  25. #include "Thread.h"
  26. #include <signal.h>
  27. #include <memory>
  28. using namespace std;
  29. template<class T> class CSignalHandler
  30. {
  31. public:
  32. using MT = CSignalHandler<T>;
  33. using SI = siginfo_t;
  34. using SS = sigset_t;
  35. using CHandlerThread = CThread<MT, const SS, VOID>;
  36. using F = VOID (T::*)(const SI*);
  37. using SF = VOID (*)(const SI*);
  38. using SSPTR = unique_ptr<SS>;
  39. friend CHandlerThread;
  40. public:
  41. BOOL Setup(SF pFunc, const SS* pSigSet, BOOL bRestorOnCancel = TRUE)
  42. {
  43. return Setup((__CFakeRunnerClass_*)nullptr, *(F*)&pFunc, pSigSet, bRestorOnCancel);
  44. }
  45. BOOL Setup(T* pRunner, F pFunc, const SS* pSigSet, BOOL bRestorOnCancel = TRUE)
  46. {
  47. ASSERT_CHECK_EINVAL(pSigSet != nullptr);
  48. m_pssPre = make_unique<SS>();
  49. int rs = pthread_sigmask(SIG_BLOCK, pSigSet, m_pssPre.get());
  50. if(rs != NO_ERROR)
  51. {
  52. m_pssPre = nullptr;
  53. ::SetLastError(rs);
  54. return FALSE;
  55. }
  56. m_pRunner = pRunner;
  57. m_pFunc = pFunc;
  58. m_pssCur = make_unique<SS>();
  59. ::CopyPlainObject(m_pssCur.get(), pSigSet);
  60. BOOL isOK = m_thHandler.Start(this, &MT::ThreadFunc, m_pssCur.get());
  61. if(isOK && !bRestorOnCancel)
  62. m_pssPre = nullptr;
  63. else if(!isOK)
  64. EXECUTE_RESTORE_ERROR(Reset());
  65. return isOK;
  66. }
  67. BOOL Cancel()
  68. {
  69. BOOL isOK = m_thHandler.IsRunning();
  70. if(isOK)
  71. {
  72. isOK = m_thHandler.Interrupt();
  73. isOK &= m_thHandler.Join();
  74. }
  75. isOK &= Reset();
  76. return isOK;
  77. }
  78. BOOL IsRunning () {return m_thHandler.IsRunning();}
  79. T* GetRunner () {return m_pRunner;}
  80. F GetFunc () {return m_pFunc;}
  81. SF GetSFunc () {return *(SF*)&m_pFunc;}
  82. THR_ID GetThreadID () {return m_thHandler.GetThreadID();}
  83. NTHR_ID GetNativeID () {return m_thHandler.GetNativeID();}
  84. private:
  85. VOID ThreadFunc(const SS* pSigSet)
  86. {
  87. ASSERT(pSigSet == m_pssCur.get());
  88. SI si;
  89. ZeroObject(si);
  90. while(!::IsThreadInterrupted())
  91. {
  92. #if !defined(__ANDROID__)
  93. int rs = NO_EINTR_EXCEPT_THR_INTR_INT(sigwaitinfo(pSigSet, &si));
  94. #else
  95. int rs = NO_EINTR_EXCEPT_THR_INTR_INT(sigwait(pSigSet, &si.si_signo));
  96. #endif
  97. if(IS_HAS_ERROR(rs))
  98. {
  99. if(IS_ERROR(EINTR))
  100. {
  101. ASSERT(::IsThreadInterrupted());
  102. break;
  103. }
  104. ERROR_ABORT();
  105. }
  106. Run((T*)nullptr, &si);
  107. }
  108. }
  109. template<typename T_, typename = enable_if_t<!is_same<T_, __CFakeRunnerClass_>::value>>
  110. VOID Run(T_*, const SI* pSigSet) {(m_pRunner->*m_pFunc)(pSigSet);}
  111. VOID Run(__CFakeRunnerClass_*, const SI* pSigSet) {(*(SF*)&m_pFunc)(pSigSet);}
  112. BOOL Reset()
  113. {
  114. BOOL isOK = TRUE;
  115. if(m_pssPre)
  116. {
  117. isOK = (pthread_sigmask(SIG_SETMASK, m_pssPre.get(), nullptr) == NO_ERROR);
  118. m_pssPre = nullptr;
  119. }
  120. m_pssCur = nullptr;
  121. m_pRunner = nullptr;
  122. m_pFunc = nullptr;
  123. return isOK;
  124. }
  125. public:
  126. CSignalHandler()
  127. {
  128. }
  129. virtual ~CSignalHandler()
  130. {
  131. Cancel();
  132. }
  133. DECLARE_NO_COPY_CLASS(CSignalHandler)
  134. private:
  135. T* m_pRunner;
  136. F m_pFunc;
  137. SSPTR m_pssCur;
  138. SSPTR m_pssPre;
  139. CHandlerThread m_thHandler;
  140. };
  141. using CStaticSignalHandler = CSignalHandler<__CFakeRunnerClass_>;