Just for travis
RFC: Assert on probable deadlocks if the second lock isnt try_lock #5515
pull TheBlueMatt wants to merge 1 commits into bitcoin:master from TheBlueMatt:probable_assert changing 1 files +39 −10-
TheBlueMatt commented at 10:48 AM on December 20, 2014: member
- TheBlueMatt force-pushed on Dec 20, 2014
- TheBlueMatt renamed this:
TRAVIS_TEST: Assert on probable deadlocks if the second lock isnt try_lock
RFC: Assert on probable deadlocks if the second lock isnt try_lock
on Dec 20, 2014 -
TheBlueMatt commented at 9:15 PM on December 20, 2014: member
Since travis passes, I figured we might actually consider this...essentially, it asserts that we dont have deadlocks assuming: (a) no locking-conditions are based on data other than the current set of locked locks and (b) if we do a TRY_LOCK, and it fails, we will immediately bail out and just skip that section of code. Since DEBUG_LOCKORDER is pretty much travis-only, if it might crash in cases that regular bitcoind might not, I dont really mind.
-
TheBlueMatt commented at 9:16 PM on December 20, 2014: member
Mostly, the DEBUG_LOCKORDER warnings arent even shown by travis anymore (they're just hidden behind the debug.log, so the only thing that flag does is check the lock assertions), so I figure we should have some semi-automated screeching if common-path code has lock inversions.
- laanwj added the label Tests on Jan 8, 2015
- laanwj added the label Improvement on Jan 8, 2015
-
laanwj commented at 12:00 PM on April 1, 2015: member
Concept ACK, but this makes the deadlock detection code kind of complex. I can't immediately see whether it's correct or wrong.
-
gavinandresen commented at 2:19 PM on April 1, 2015: contributor
Hmmm....
Would this work instead? Modify sync.h CMutexLock::TryEnter to only call EnterCritical() if the lock is successfully acquired?
bool TryEnter(const char* pszName, const char* pszFile, int nLine) { lock.try_lock(); if (lock.owns_lock() EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true); return lock.owns_lock(); }(or, in other words: just ignore TRY_LOCKS that don't acquire the lock)
-
TheBlueMatt commented at 5:30 PM on April 3, 2015: member
@gavinandresen No, because often you see warnings because you have a lock(B) followed by a try_lock(A) and a lock(A) followed by a lock(B) at different times, you'll get a warning, but your suggestion would ignore it because you didnt actually see a deadlock.
Also, you cant just ignore try_locks entirely because it is very easy to create a deadlock with a try_lock.
-
gavinandresen commented at 5:56 PM on April 3, 2015: contributor
@TheBlueMatt : maybe I'm being dense... but:
If we get: lock(B) then a successful (lock-acquired) try_lock(A), then the lockorders map will contain "B then A". If at any point in the future lock(A) is followed by lock(B), a warning will be triggered -- my suggestion doesn't require that there be an actual deadlock.
I'm not suggesting that try_lock be ignored entirely....
-
TheBlueMatt commented at 4:06 AM on April 4, 2015: member
@gavinandresen Yes, and if a warning were triggered in that (beningn) case, then you'd see things crash on the new assert?
-
sipa commented at 4:31 AM on April 8, 2015: member
Haven't spent too much time thinking about this, but having (A, B) in one place and (B, try A) in another place can never cause a deadlock. I believe that the correct checking behaviour is to add any acquired lock to the table, but never do a deadlock check when entering a try_lock.
-
TheBlueMatt commented at 1:25 PM on April 8, 2015: member
@sipa: Consider the case A, tryB, C and C, tryB, A. This is actually not a deadlock, but if you simply skip the deadlock check for B, you'll get an error.
-
TheBlueMatt commented at 1:26 PM on April 8, 2015: member
IIRC, there was a similar case that I saw that prompted this pull.
-
gavinandresen commented at 1:43 PM on April 8, 2015: contributor
@TheBlueMatt : sorry, I WAS just being dense.
I'm with @laanwj -- ACK on the concept, but I'm having trouble convincing myself the code is correct (I may just need more caffeine before thinking about it some more). It feels like there should be a simpler solution.
-
sipa commented at 2:45 PM on April 8, 2015: member
Interesting. I agree (a,try b,c),(c,try b,a)) is not a deadlock, but it is not something any code should be doing - it looks extremely fragile (remove a lock, and turn it into a deadlock). So I'd rather trigger deadlock warnings for it too.
-
TheBlueMatt commented at 4:07 PM on April 8, 2015: member
IIRC we (used to) do something like that. We may not anymore, but some of the network processing stuff is a mess.
On April 8, 2015 3:46:03 PM GMT+01:00, Pieter Wuille notifications@github.com wrote:
Interesting. I agree (a,try b,c),(c,try b,a)) is not a deadlock, but it is not something any code should be doing - it looks extremely fragile (remove a lock, and turn it into a deadlock). So I'd rather trigger deadlock warnings for it too.
Reply to this email directly or view it on GitHub: #5515 (comment)
-
Assert on probable deadlocks if the second lock isnt try_lock 0fcc4e1e04
- TheBlueMatt force-pushed on Jul 22, 2015
-
TheBlueMatt commented at 11:53 PM on July 22, 2015: member
@sipa checked, turns out the deadlock detection code never called potential_deadlock_detected for TRY_LOCKs so we definitely still do require the code in this pull before we can assert on deadlocks. Also rebased and added a comment so that this is more readable.
- laanwj merged this on Jul 23, 2015
- laanwj closed this on Jul 23, 2015
- laanwj referenced this in commit d946e9a848 on Jul 23, 2015
- TheBlueMatt deleted the branch on Jul 24, 2015
- laanwj referenced this in commit a4fe57da62 on Aug 6, 2015
- zkbot referenced this in commit 57d420e2f8 on Feb 15, 2017
- zkbot referenced this in commit 88c209dba6 on Feb 20, 2017
- zkbot referenced this in commit dadb1ab74c on Mar 3, 2017
- MarcoFalke locked this on Sep 8, 2021