| 81 | } |
| 82 | |
| 83 | DWORD DebugThreadWatch::Execute() |
| 84 | { |
| 85 | DWORD lastAlive = ::GetTickCount(); |
| 86 | for (;;) |
| 87 | { |
| 88 | Foundation::SignaledObject* wait[] = {&_terminate, &_keepAlive}; |
| 89 | int waitTime, waitTime0; |
| 90 | { |
| 91 | Foundation::ScopeLockSection lock(_lock); |
| 92 | waitTime0 = waitTime = _timeOut; |
| 93 | if (waitTime < 0 || waitTime > 10000) |
| 94 | { |
| 95 | waitTime = 10000; |
| 96 | } |
| 97 | } |
| 98 | DWORD start = ::GetTickCount(); |
| 99 | int which = Foundation::SignaledObject::WaitForMultiple(wait, sizeof(wait) / sizeof(*wait), waitTime); |
| 100 | if (which == 0) |
| 101 | { |
| 102 | return 0; // _terminate event |
| 103 | } |
| 104 | else if (which == 1) // alive event |
| 105 | { |
| 106 | lastAlive = ::GetTickCount(); |
| 107 | DWORD delay = lastAlive - start; |
| 108 | if (delay > static_cast<DWORD>(waitTime - 2000) || |
| 109 | delay > 2500) // waitTime clamped to [0,10000], safe to cast |
| 110 | { |
| 111 | LOG_DEBUG(Core, "No alive in {} of {} ms", delay, waitTime); |
| 112 | LOG_DEBUG(Core, " check another threads -- add ProgressRefresh()"); |
| 113 | } |
| 114 | // no more event expected until told by NextAlive |
| 115 | } |
| 116 | else |
| 117 | { |
| 118 | if (waitTime0 >= 0 && waitTime0 < 20000 && _enable > 0) |
| 119 | { |
| 120 | LOG_DEBUG(Core, "Freeze detected: no alive in {} ms", waitTime); |
| 121 | ::SuspendThread(_mainThreadHandle); |
| 122 | if (::GetTickCount() - lastAlive >= 30000) |
| 123 | { |
| 124 | // fatal situation - terminate |
| 125 | ::DDTerm(); |
| 126 | exit(1); |
| 127 | } |
| 128 | else |
| 129 | { |
| 130 | ::ResumeThread(_mainThreadHandle); |
| 131 | } |
| 132 | } |
| 133 | } |
| 134 | } |
| 135 | // Unreachable - infinite loop above always returns via _terminate event |
| 136 | } |
| 137 | |
| 138 | DebugThreadWatch::~DebugThreadWatch() = default; |
| 139 |
no test coverage detected