MCPcopy Create free account
hub / github.com/CodeSentryAI/lockbud / detect_deadlock

Method detect_deadlock

src/detector/lock/mod.rs:589–662  ·  view source on GitHub ↗

First detect doublelock on each relation(a, b), use non-doublelock relations to build `ConflictLockGraph`. Then find the cycles in `ConflictLockGraph` as conflictlock.

(
        &self,
        lockguards: &LockGuardMap<'tcx>,
        callgraph: &'a CallGraph<'tcx>,
        alias_analysis: &mut AliasAnalysis<'a, 'tcx>,
    )

Source from the content-addressed store, hash-verified

587 }
588 } else {
589 // if is terminator
590 for succ_bb in body[loc.block].terminator().successors() {
591 let succ = Location {
592 block: succ_bb,
593 statement_index: 0,
594 };
595 // union and reprocess if changed
596 let changed = states.get_mut(&succ).unwrap().union_in_place(after.clone());
597 if changed {
598 worklist.push_back(succ);
599 }
600 }
601 }
602 }
603 states
604 }
605
606 /// First detect doublelock on each relation(a, b),
607 /// use non-doublelock relations to build `ConflictLockGraph`.
608 /// Then find the cycles in `ConflictLockGraph` as conflictlock.
609 fn detect_deadlock<'a>(
610 &self,
611 lockguards: &LockGuardMap<'tcx>,
612 callgraph: &'a CallGraph<'tcx>,
613 alias_analysis: &mut AliasAnalysis<'a, 'tcx>,
614 ) -> Vec<Report> {
615 let mut reports = Vec::new();
616 let mut conflictlock_graph = ConflictLockGraph::new();
617 let mut relation_to_nodes = FxHashMap::default();
618 // Detect doublelock:
619 // forall relation(a, b): deadlock(a, b) => doublelock(a, b)
620 for (a, b) in &self.lockguard_relations {
621 let (possibility, reason) = deadlock_possibility(a, b, lockguards, alias_analysis);
622 match possibility {
623 DeadlockPossibility::Probably | DeadlockPossibility::Possibly => {
624 let diagnosis = diagnose_doublelock(a, b, lockguards, callgraph, self.tcx);
625 let report = Report::DoubleLock(ReportContent::new(
626 "DoubleLock".to_owned(),
627 format!("{:?}", possibility),
628 diagnosis,
629 "The first lock is not released when acquiring the second lock".to_owned(),
630 ));
631 reports.push(report);
632 }
633 _ if NotDeadlockReason::RecursiveRead != reason
634 && NotDeadlockReason::SameSpan != reason =>
635 {
636 // if unlikely doublelock, add the pair into graph to check conflictlock
637 // when the lockguards are gen by call rather than move
638 if !lockguards[a].is_gen_only_by_move() && !lockguards[b].is_gen_only_by_move()
639 {
640 let node = conflictlock_graph.add_node((*a, *b));
641 relation_to_nodes.insert((*a, *b), node);
642 }
643 }
644 _ => {}
645 }
646 }

Callers 1

detectMethod · 0.80

Calls 9

deadlock_possibilityFunction · 0.85
diagnose_doublelockFunction · 0.85
diagnose_one_relationFunction · 0.85
is_gen_only_by_moveMethod · 0.80
add_nodeMethod · 0.80
insertMethod · 0.80
add_edgeMethod · 0.80
cycle_pathsMethod · 0.80
node_weightMethod · 0.80

Tested by

no test coverage detected