Skip to content

[DRAFT] [racerd] apply the lock releases of callees and destructors to their callers - #2206

Draft
VladimirMakaev wants to merge 1 commit into
facebook:mainfrom
VladimirMakaev:racerd-callee-unlock
Draft

VladimirMakaev wants to merge 1 commit into
facebook:mainfrom
VladimirMakaev:racerd-callee-unlock

Conversation

@VladimirMakaev

@VladimirMakaev VladimirMakaev commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

RacerD counted held locks with a saturating counter and skipped destructors, so unlock helpers and
custom RAII guards never released their caller's lock:

struct Guard {
  explicit Guard(std::mutex& m) : m_(m) { m_.lock(); }
  ~Guard() { m_.unlock(); }
  std::mutex& m_;
};

void C::set(int v) { std::lock_guard<std::mutex> l(mu_); x_ = v; }

int C::get() {
  { Guard g(mu_); }
  return x_; // Infer missed: lock consistency violation
}

Track the lock state as its effect on the locks held on entry, n -> max(0, n - released) + held,
which composes across calls, and analyse destructors for this effect only. A guard that is not a
local variable, e.g. a member, may release a lock held on entry.

Limitations:

Test plan

New cpp/racerd/unlock_in_callee.cpp. In java/racerd, FN_releaseLockInCalleeBad is now
reported and renamed, and FP_releaseLockOfCallerInCalleeOk shows the first limitation. The
codetoanalyze tests pass.

…callers

RacerD counted held locks with a saturating counter and skipped destructors, so unlock helpers and
custom RAII guards never released their caller's lock:

```cpp
struct Guard {
  explicit Guard(std::mutex& m) : m_(m) { m_.lock(); }
  ~Guard() { m_.unlock(); }
  std::mutex& m_;
};

void C::set(int v) { std::lock_guard<std::mutex> l(mu_); x_ = v; }

int C::get() {
  { Guard g(mu_); }
  return x_; // Infer missed: lock consistency violation
}
```

Track the lock state as its effect on the locks held on entry, `n -> max(0, n - released) + held`,
which composes across calls, and analyse destructors for this effect only. A guard that is not a
local variable, e.g. a member, may release a lock held on entry.

Limitations:
- locks have no identity: a lock held on entry that a callee releases is taken to be the last lock
  its caller acquired;
- guard members are assumed to own their lock when destroyed;
- classes that lock only through callees are still not considered concurrent (see facebook#2211).

## Test plan

New `cpp/racerd/unlock_in_callee.cpp`. In `java/racerd`, `FN_releaseLockInCalleeBad` is now
reported and renamed, and `FP_releaseLockOfCallerInCalleeOk` shows the first limitation. The
codetoanalyze tests pass.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant