| 129 | } |
| 130 | |
| 131 | void KernelStackWatchdog::RunThread() { |
| 132 | while (true) { |
| 133 | MonoDelta delta = MonoDelta::FromMilliseconds(FLAGS_hung_task_check_interval_ms); |
| 134 | if (finish_.WaitFor(delta)) { |
| 135 | // Watchdog exiting. |
| 136 | break; |
| 137 | } |
| 138 | |
| 139 | // Don't send signals while the debugger is running, since it makes it hard to |
| 140 | // use. |
| 141 | if (IsBeingDebugged()) { |
| 142 | continue; |
| 143 | } |
| 144 | |
| 145 | // Prevent threads from deleting their TLS objects between the snapshot loop and the sending of |
| 146 | // signals. This makes it safe for us to access their TLS. |
| 147 | // |
| 148 | // NOTE: it's still possible that the thread will have exited in between grabbing its pointer |
| 149 | // and sending a signal, but DumpThreadStack() already is safe about not sending a signal |
| 150 | // to some other non-Kudu thread. |
| 151 | MutexLock l(unregister_lock_); |
| 152 | |
| 153 | // Take the snapshot of the thread information under a short lock. |
| 154 | // |
| 155 | // 'tls_lock_' prevents new threads from starting, so we don't want to do any lengthy work |
| 156 | // (such as gathering stack traces) under this lock. |
| 157 | TLSMap tls_map_copy; |
| 158 | vector<unique_ptr<TLS>> to_delete; |
| 159 | { |
| 160 | lock_guard<simple_spinlock> l(tls_lock_); |
| 161 | to_delete.swap(pending_delete_); |
| 162 | tls_map_copy = tls_by_tid_; |
| 163 | } |
| 164 | // Actually delete the no-longer-used TLS entries outside of the lock. |
| 165 | to_delete.clear(); |
| 166 | |
| 167 | MicrosecondsInt64 now = GetMonoTimeMicros(); |
| 168 | for (const auto& entry : tls_map_copy) { |
| 169 | pid_t p = entry.first; |
| 170 | TLS::Data* tls = &entry.second->data_; |
| 171 | TLS::Data tls_copy; |
| 172 | tls->SnapshotCopy(&tls_copy); |
| 173 | for (int i = 0; i < tls_copy.depth_; i++) { |
| 174 | const TLS::Frame* frame = &tls_copy.frames_[i]; |
| 175 | |
| 176 | int paused_ms = (now - frame->start_time_) / 1000; |
| 177 | if (paused_ms > frame->threshold_ms_) { |
| 178 | string kernel_stack; |
| 179 | Status s = GetKernelStack(p, &kernel_stack); |
| 180 | if (!s.ok()) { |
| 181 | // Can't read the kernel stack of the pid, just ignore it. |
| 182 | kernel_stack = "(could not read kernel stack)"; |
| 183 | } |
| 184 | |
| 185 | string user_stack = DumpThreadStack(p); |
| 186 | |
| 187 | // If the thread exited the frame we're looking at in between when we started |
| 188 | // grabbing the stack and now, then our stack isn't correct. We shouldn't log it. |
no test coverage detected