| 134 | } |
| 135 | |
| 136 | ProcessTracer::ProcessTracer(pid_t pid) |
| 137 | { |
| 138 | std::unordered_map<int, int> error_by_tid; |
| 139 | |
| 140 | bool found_new_tid = true; |
| 141 | while (found_new_tid) { |
| 142 | found_new_tid = false; |
| 143 | |
| 144 | auto tids = getProcessTids(pid); |
| 145 | for (auto& tid : tids) { |
| 146 | if (d_tids.count(tid)) { |
| 147 | continue; // already stopped |
| 148 | } |
| 149 | |
| 150 | auto err_it = error_by_tid.find(tid); |
| 151 | if (err_it != error_by_tid.end()) { |
| 152 | // We got an error for this TID on the last iteration. |
| 153 | // Since we found the TID again this iteration, it still |
| 154 | // belongs to us and should have been stoppable. |
| 155 | detachFromProcess(); |
| 156 | |
| 157 | int error = err_it->second; |
| 158 | if (error == EPERM) { |
| 159 | throw std::runtime_error(PERM_MESSAGE); |
| 160 | } |
| 161 | throw std::system_error(error, std::generic_category()); |
| 162 | } |
| 163 | |
| 164 | found_new_tid = true; |
| 165 | |
| 166 | LOG(INFO) << "Trying to stop thread " << tid; |
| 167 | long ret = ptrace(PTRACE_ATTACH, tid, nullptr, nullptr); |
| 168 | if (ret < 0) { |
| 169 | int error = errno; |
| 170 | LOG(WARNING) << "Failed to attach to thread " << tid << ": " << strerror(error); |
| 171 | error_by_tid.emplace(tid, error); |
| 172 | continue; |
| 173 | } |
| 174 | |
| 175 | // Add each tid as we attach: these are the tids we detach from. |
| 176 | d_tids.insert(tid); |
| 177 | |
| 178 | LOG(INFO) << "Waiting for thread " << tid << " to be stopped"; |
| 179 | ret = waitpid(tid, nullptr, WUNTRACED); |
| 180 | if (ret < 0) { |
| 181 | // In some old kernels is not possible to use WUNTRACED with |
| 182 | // threads (only the main thread will return a non zero value). |
| 183 | if (tid == pid || errno != ECHILD) { |
| 184 | detachFromProcess(); |
| 185 | } |
| 186 | } |
| 187 | LOG(INFO) << "Thread " << tid << " stopped"; |
| 188 | } |
| 189 | } |
| 190 | LOG(INFO) << "All " << d_tids.size() << " threads stopped"; |
| 191 | } |
| 192 | |
| 193 | void |
nothing calls this directly
no test coverage detected