Merge lp:~raof/mir/fix-lock-inversion into lp:mir
Status: | Merged |
---|---|
Approved by: | Alan Griffiths |
Approved revision: | no longer in the source branch. |
Merged at revision: | 4215 |
Proposed branch: | lp:~raof/mir/fix-lock-inversion |
Merge into: | lp:mir |
Diff against target: |
152 lines (+60/-40) 3 files modified
src/client/buffer_vault.cpp (+59/-12) src/client/buffer_vault.h (+1/-0) tests/unit-tests/client/test_buffer_vault.cpp (+0/-28) |
To merge this branch: | bzr merge lp:~raof/mir/fix-lock-inversion |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mir CI Bot | continuous-integration | Approve | |
Alan Griffiths | Approve | ||
Review via email: mp+328069@code.launchpad.net |
Commit message
mcl::BufferVault: Fix lock inversion.
~BufferVault takes BufferVault::mutex and then calls AtomicCallback:
which takes AtomicCallback:
The RPC subsystem calls buffer->callback(), which takes AtomicCallback:
BufferVault:
This is clearly a disaster waiting to happen.
Instead, move to a two-phase destruction approach:
1) Lock BufferVault::mutex, set a flag telling callbacks to bail, and collect all the existing
buffers.
2) Drop the lock, and use buffer-
3) Don't bother telling the server to release any buffers; they're associated with the
BufferStream that we're in the process of destroying, and will get cleaned up there.
Description of the change
This, unfortunately, moves the deadlock into a different place, but I think it's a correct change.
> The RPC subsystem calls buffer->callback(), which takes :mutex and then calls BufferVault: :wire_transfer_ inbound. ..
> AtomicCallback:
> which immediately takes BufferVault::mutex.
This (pre-existing code) is hard to reason about, the extra logic doesn't help.
Would it be any more complex to make BufferVault::mutex a std::recursive_ mutex? (The above is all on a single thread.)