Check if 'target_id' is holding the same lock as another thread(s). The search within 'blocking_on' starts with the threads listed in 'candidate_ids'. 'seen_ids' contains any threads that are considered already traversed in the search. Keyword arguments: target_id -- The t
(target_id, *, seen_ids, candidate_ids, blocking_on)
| 181 | |
| 182 | |
| 183 | def _has_deadlocked(target_id, *, seen_ids, candidate_ids, blocking_on): |
| 184 | """Check if 'target_id' is holding the same lock as another thread(s). |
| 185 | |
| 186 | The search within 'blocking_on' starts with the threads listed in |
| 187 | 'candidate_ids'. 'seen_ids' contains any threads that are considered |
| 188 | already traversed in the search. |
| 189 | |
| 190 | Keyword arguments: |
| 191 | target_id -- The thread id to try to reach. |
| 192 | seen_ids -- A set of threads that have already been visited. |
| 193 | candidate_ids -- The thread ids from which to begin. |
| 194 | blocking_on -- A dict representing the thread/blocking-on graph. This may |
| 195 | be the same object as the global '_blocking_on' but it is |
| 196 | a parameter to reduce the impact that global mutable |
| 197 | state has on the result of this function. |
| 198 | """ |
| 199 | if target_id in candidate_ids: |
| 200 | # If we have already reached the target_id, we're done - signal that it |
| 201 | # is reachable. |
| 202 | return True |
| 203 | |
| 204 | # Otherwise, try to reach the target_id from each of the given candidate_ids. |
| 205 | for tid in candidate_ids: |
| 206 | if not (candidate_blocking_on := blocking_on.get(tid)): |
| 207 | # There are no edges out from this node, skip it. |
| 208 | continue |
| 209 | elif tid in seen_ids: |
| 210 | # bpo 38091: the chain of tid's we encounter here eventually leads |
| 211 | # to a fixed point or a cycle, but does not reach target_id. |
| 212 | # This means we would not actually deadlock. This can happen if |
| 213 | # other threads are at the beginning of acquire() below. |
| 214 | return False |
| 215 | seen_ids.add(tid) |
| 216 | |
| 217 | # Follow the edges out from this thread. |
| 218 | edges = [lock.owner for lock in candidate_blocking_on] |
| 219 | if _has_deadlocked(target_id, seen_ids=seen_ids, candidate_ids=edges, |
| 220 | blocking_on=blocking_on): |
| 221 | return True |
| 222 | |
| 223 | return False |
| 224 | |
| 225 | |
| 226 | class _ModuleLock: |
no test coverage detected
searching dependent graphs…