Skip to content

Conversation

practicalswift
Copy link
Contributor

@practicalswift practicalswift commented Sep 3, 2017

Add additional Clang thread safety analysis annotations as discussed with @sipa (#10866 (comment)) and others.

This is a follow-up to #10866 which this PR is rebased upon (awaiting merge of #10866). The first three commits (8a1dc09, e022990 and cbae151) can be reviewed in #10866.

This PR contains three types of changes:

  1. Add missing locks (based on the GUARDED_BY(...) analysis below). Please review thoroughly.
  2. Add GUARDED_BY(...) annotations to allow for Clang's thread safety analysis at compile-time. Does not change run-time behaviour.
  3. Add EXCLUSIVE_LOCKS_REQUIRED(...) annotations to allow for Clang's thread safety analysis at compile-time. Does not change run-time behaviour.

Background reading: The "C/C++ Thread Safety Analysis" paper (Hutchins, Ballman & Sutherland, 2014) paper describing Clang thread safety analysis and how it is used for the Google C++ codebase:

They essentially provide a static type system for threads, and can detect potential race conditions and deadlocks. This paper describes Clang Thread Safety Analysis, a tool which uses annotations to declare and enforce thread safety policies in C and C++ programs.
[…]
It has been deployed on a large scale at Google; all C++ code at Google is now compiled with thread safety analysis enabled by default.
[…]
The GUARDED_BY attribute declares that a thread must lock mu before it can read or write to balance, thus ensuring that the increment and decrement operations are atomic. Similarly, REQUIRES declares that the calling thread must lock mu before calling withdrawImpl. Because the caller is assumed to have locked mu, it is safe to modify balance within the body of the method.

@sipa
Copy link
Member

sipa commented Sep 4, 2017

Awesome, I'm very happy to see someone work on this again.

@practicalswift practicalswift force-pushed the guarded-by-trivial branch 2 times, most recently from 763b3d1 to 8729f81 Compare September 4, 2017 06:52
@sipa
Copy link
Member

sipa commented Sep 4, 2017

You must have introduced a lock inversion, based on the Travis output.

@promag
Copy link
Contributor

promag commented Sep 4, 2017

Squash commits Add GUARDED_BY(cs_KeyStore) and also Add GUARDED_BY(cs) annotation.

@practicalswift practicalswift force-pushed the guarded-by-trivial branch 3 times, most recently from b808f4c to d72e1e4 Compare September 4, 2017 14:33
@practicalswift
Copy link
Contributor Author

practicalswift commented Sep 4, 2017

@sipa Thanks for letting me know! I've now removed the commit with the incorrectly added LOCK(walletInstance->cs_KeyStore) in wallet.cpp that caused the lock inversion. Do you which variables cs_KeyStore is meant to guard?

@practicalswift
Copy link
Contributor Author

@promag Fixed! :-) Regarding the repeated GUARDED_BY(cs) commit messages - these actually refer to different cs:es. To make things less confusing I've now disambiguated them by adding the class names in the commit message.

Furthermore I've added an commit which renames renames CAddrMan.cs to CAddrMan.cs_addrMan, and CTxMemPool.cs to CTxMemPool.cs_txMemPool.

@TheBlueMatt
Copy link
Contributor

Concept ACK. This will generate some turbulence in terms of needing to rebase a ton of existing PRs, so maybe it makes sense to break this into several PRs which only touch given modules? In any case, excited to see this stuff happen.

@laanwj
Copy link
Member

laanwj commented Sep 6, 2017

Concept ACK. Though I'm not sure what a good time to merge a huge, spread-out (though low-risk) change like this is. Maybe just before the 0.16 split?

@practicalswift
Copy link
Contributor Author

practicalswift commented Sep 11, 2017

@laanwj Good point! When is the 0.16 split expected to happen?

The smaller PR #10866 lays the groundwork for the subsequent thread-safety-analysis annotation work. Having that PR merged a bit earlier would help a lot :-)

@practicalswift
Copy link
Contributor Author

@TheBlueMatt Sure, I can split this PR into multiple parts to ease reviewing! Just let me know which parts/modules to split it on :-) To avoid duplicating the commits in #10866 we should probably wait until #10866 is merged before splitting this PR up. Sounds reasonable?

@practicalswift
Copy link
Contributor Author

practicalswift commented Sep 11, 2017

@sipa @TheBlueMatt @laanwj Thanks for reviewing and thanks for the encouragement! Do you happen to know which core developers that would be appropriate reviewers for this work (on a deeper GUARDED_BY(…) level for each module)?

The types of errors I might need some help from reviewers to avoid:

  • False positives: Too restrictive lock requirements. Requiring a lock where a lock is not needed. More concretely: unnecessary GUARDED_BY(…) annotations. (The EXCLUSIVE_LOCKS_REQUIRED(…) annotations follow more or less mechanically for the GUARDED_BY(…).)
  • False negatives: Missing lock requirements. Not requiring a lock where a lock is needed. More concretely: missing GUARDED_BY(…) annotations.

And perhaps most importantly: help reviewing that the added locks in this PR looks reasonable. In constrast to the annotations they alter run-time behaviour.

There are a couple of AssertLockHeld(…):s that I've been unable to map to variables being guarded. I might need some help to track those down to add the corresponding GUARDED_BY(…):s (and hence EXCLUSIVE_LOCKS_REQUIRED(…)). I'm a bit hesitant to just add EXCLUSIVE_LOCKS_REQUIRED(…) to match the AssertLockHeld(…) (which would be trivial) since that methodology hides the fact that the guard required hasn't been explicitly stated using an GUARDED_BY(…) annotation yet.

@practicalswift
Copy link
Contributor Author

practicalswift commented Sep 13, 2017

The code base contains 37 locks and in the process of documenting them I compiled this list of the initial creators of each lock. These lock introducers would likely be the best possible reviewers for the GUARDED_BY(…):s in this PR for "their" respective locks :-)

Bitcoin locks hall of fame

Locks introduced by currently active core devs:

  • @TheBlueMatt (10 locks): cs_filter, cs_args, cs_vSend, cs_most_recent_block, cs_callbacks_pending (previously m_cs_callbacks_pending), cs_vAddedNodes, cs_SubVer, cs_addrName, cs_addrLocal, cs_sendProcessing
  • @sipa (8 locks): cs_KeyStore, cs_addrMan (previously cs), cs_mapLocalHost, cs_LastBlockFile, cs_vOneShots, cs_pathCached (previously csPathCached), cs_nTimeOffset, cs_nBlockSequenceId
  • @theuni (3 locks): cs_hSocket, cs_vRecv, cs_vProcessMsg
  • @morcos (2 locks): cs_feeEstimator, cs_feeFilter
  • @gmaxwell (1 lock): cs_warnings

Previous lock introducers:

  • Locks included in the first commit in the repo (Satoshi locks!): cs_main, cs_vNodes, cs_db, cs_inventory, cs_Shutdown
  • gavinandresen: cs_wallet, cs_txMemPool (previously cs), cs_setBanned
  • sje397: cs_totalBytesSent, cs_totalBytesRecv
  • Clark Gaebel: cs_test (previously cs)
  • domob1812: cs_rpcWarmup
  • Philip Kaufmann: cs_proxyInfos

@practicalswift
Copy link
Contributor Author

practicalswift commented Sep 14, 2017

I'm now down to only four remaining AssertLockHeld(…):s for which I'm unable to identify which specific variable the lock in question is being a guard for.

These are the four cases I need help with:

For each of the above cases I see two alternatives:

  1. A GUARDED_BY(…) for some variable accessed directly or indirectly is missing.
  2. The lock is not technically necessary.

@practicalswift
Copy link
Contributor Author

I've now documented the five places where I'm opting out of thread-safety analysis for various reasons (using the NO_THREAD_SAFETY_ANALYSIS annotation): b72ad1f43d96b6f63e7a4046f31af085da4e86db

Please let me know if there is a way to remove any of these opt-outs.

@TheBlueMatt
Copy link
Contributor

@practicalswift

  • GetBlockScriptFlags() needs cs_main for versionbitscache (maybe others, but probably just that?)
  • AcceptBlockHeader is mostly for mapBlockIndex it looks like
  • RemoveWatchOnly looks like it may need to be an atomic operation, but I haven't dug into it too much. It may very well be the case that you'd miss a NotifyWatchonlyChanged fire if you have an AddWatchOnly and a RemoveWatchOnly call at the same time (though I don't know if there are any negative effects from doing so).
  • RescanFromTime indeed does not appear to require cs_wallet (obviously ScanForWalletTransactions does, but it takes it itself). It obviously needs cs_main, though.

@practicalswift
Copy link
Contributor Author

@TheBlueMatt Thanks! I'll look into the suggested fixes.

@practicalswift
Copy link
Contributor Author

@jonasschnelli @TheBlueMatt In CDB::PeriodicFlush(CWalletDBWrapper& dbw) (code) we are currently trying to lock bitdb.cs_db – shouldn't that lock be on env->cs_db instead (CDBEnv *env = dbw.env)? Or am I reading it wrong? :-)

@practicalswift
Copy link
Contributor Author

@laanwj, after some digging I found your bitdb reference cleanup commit be9e1a9, perhaps you know the answer to the question about the bitdb.cs_db lock above? :-)

@maflcko
Copy link
Member

maflcko commented Jan 10, 2018

Needs rebase.
For the purpose of easing review and speeding up merge: What about submitting a subset of this that only renames the comments // protected by ${cs} to GUARDED_BY(${cs}). Assuming that the existing comments are reviewed such a subset should be refactoring-only and easier to merge.

@laanwj laanwj modified the milestones: 0.16.0, 0.17.0 Jan 11, 2018
@practicalswift
Copy link
Contributor Author

practicalswift commented Jan 31, 2018

@MarcoFalke Do you mean a new PR with the GUARDED_BY(…):s in this PR added instead as comments // GUARDED_BY(…)? Sure, confirm and I'll do that.

Regarding rebasing – I suggest we merge (or close in the case of NACK) the locking related PR:s I currently have open and I'll rebase this PR on top of master after that. Makes sense?

@maflcko
Copy link
Member

maflcko commented Feb 2, 2018

Something like e7f4866, but at this point I am not sure if it is going to help review a lot.

@practicalswift
Copy link
Contributor Author

Closing. Will split this into subsets and submit as separate PR:s.

@practicalswift
Copy link
Contributor Author

practicalswift commented Mar 12, 2018

To facilitate reviewing the most important parts of this thread-safety PR (milestone 0.17.0) have been submitted as individual PR:s –

Reviews of these PR:s would be really appreciated! :-)

I'll tackle the remaining parts once the above PR:s have been merged or closed. Complete thread safety annotation coverage is not far away now! :-)

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Dec 27, 2019
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 2, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 4, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 12, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 16, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 22, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 22, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 29, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Jan 29, 2020
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>
@practicalswift practicalswift deleted the guarded-by-trivial branch April 10, 2021 19:33
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Jun 30, 2021
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Feb 10, 2022
109a858 tests: Add missing locks to tests (practicalswift)

Pull request description:

  Add missing locks to tests to satisfy lock requirements (such as `EXCLUSIVE_LOCKS_REQUIRED(...)` (Clang Thread Safety Analysis, see bitcoin#11226), `AssertLockHeld(...)` and implicit lock assumptions).

Tree-SHA512: 1aaeb1da89df1779f02fcceff9d2f8ea24a3926d421f9ea305a19be04dd0b3e63d91f6c1ed22fb7e6988343f6a5288829a387ef872cfa7b6add57bd01046b5d9
Signed-off-by: Pasta <pasta@dashboost.org>

# Conflicts:
#	src/test/test_bitcoin.cpp
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants