Skip to content

Conversation

@practicalswift
Copy link
Contributor

Reading the variable chainActive requires holding the mutex cs_main.

Prior to this commit the cs_main mutex was not held when accessing chainActive in:

while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())

@practicalswift
Copy link
Contributor Author

@luke-jr @promag, would you mind reviewing this revised version? :-)

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concept ACK.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is to create a function like:

bool KeepRunning() {
    LOCK(cs_main);
    assert(chainActive.Tip());
    return chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning();
}

And here just:

while (KeepRunning()) {
    ...
}

@promag
Copy link
Contributor

promag commented Nov 15, 2017

Restarted travis job.

Reading the variable `chainActive` requires holding the mutex `cs_main`.

Prior to this commit the `cs_main` mutex was not held when accessing
`chainActive` in:

```
while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
```
@practicalswift practicalswift force-pushed the missing-lock-in-getblocktemplate branch from dbb4a14 to 6e65f35 Compare November 15, 2017 16:43
@luke-jr
Copy link
Member

luke-jr commented Nov 15, 2017

The whole point of csBestBlock was that we shouldn't need cs_main to simply check the best block. It looks like the logic for that got lost somewhere, and I'm not sure we're even safe from races anymore. :(

Suggest instead of this, fixing csBestBlock so it is sufficient/works.

@practicalswift
Copy link
Contributor Author

practicalswift commented Nov 15, 2017

@promag Now using a lambda to keep it DRY - please re-review :-)

@practicalswift
Copy link
Contributor Author

practicalswift commented Nov 21, 2017

@luke-jr Do you mean that fixing this make things worse? If so, please describe why :-)

I'm not familiar with the csBestBlock issue you are describing, so I'm afraid I'll have to leave fixing that to someone else :-)

@practicalswift
Copy link
Contributor Author

Pinging @luke-jr :-)

@TheBlueMatt
Copy link
Contributor

No reason to wait on a "better fix" before merging this. Lets just merge and then @luke-jr can fix it in the way he wants in a cleanup follow-up.

utACK 6e65f35

@theuni
Copy link
Member

theuni commented Dec 4, 2017

I agree with @luke-jr on this one. I'd rather fix it to use csBestBlock properly than waste the time figuring out the possible impact of locking cs_main in the loop.

@TheBlueMatt
Copy link
Contributor

@theuni i find the current code relatively readable, and I'm really not at all sure what "fixing csBestBlock" means, given a condition variable is allowed to wake up spuriously whenever it wants.

@theuni
Copy link
Member

theuni commented Dec 4, 2017

@TheBlueMatt as @luke-jr mentioned, presumably cvBlockChange was at one point paired with a uint256 reflecting the miner's best known hash, which at some point got removed. We shouldn't need to take cs_main to check whether the new tip matches the cached one.

@practicalswift
Copy link
Contributor Author

practicalswift commented Dec 4, 2017

If the scope of this grows beyond this PR's goal of fixing the missing cs_main lock I'm afraid I'll have to leave that for others to fix. Let me know when a fix for the issue described by @luke-jr is available and I'll close this PR.

If that is something that is unlikely to happen soon I'd vote for merging this fix while waiting for a future better fix.

@TheBlueMatt
Copy link
Contributor

@theuni "fixing" cvBlockChanged/csBestBlock probably means wholesale removing it and replacing it with appropriate event listeners, but for that, I think, we (realistically) need to beef up the infrastructure behind CValidationInterface so that we dont end up with wallet or other things blocking each other just because they're all on the validation interface (or add some new interface for this stuff that isnt "call into RPC stuff from inside ConnectBlock"), but unless you want to do that, I really think it shouldnt block a simple lock fix.

@theuni
Copy link
Member

theuni commented Dec 4, 2017

Ok, since we re-lock cs_main before returning anyway, and since cs_main being locked for any notable period of time after a legitimate cvBlockChange notification would likely indicate a rapid 2nd block anyway, I suppose no regressions would be introduced.

So, -0 to 6e65f35. Looks correct to fix the unguarded access.

@practicalswift
Copy link
Contributor Author

Any chance of getting this merged? :-)

Copy link
Contributor

@promag promag left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 6e65f35, but I have 2 comments.

assert(chainActive.Tip());
return chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning();
};
while (KeepRunning())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry but how about plain code?

while (IsRPCRunning()) {
    {
        LOCK(cs_main);
        if (chainActive.Tip()->GetBlockHash() != hashWatchedChain) break;
    }
    ...

while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
auto KeepRunning = [&]() -> bool {
LOCK(cs_main);
assert(chainActive.Tip());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would drop the assert, otherwise should we add all over where tip is used?

@practicalswift
Copy link
Contributor Author

@promag Good suggestion. Please re-review!

@TheBlueMatt @theuni Would you mind re-reviewing in light of the latest commit? :-)

@sipa
Copy link
Member

sipa commented Mar 21, 2018

Here is an alternative: #12743

@practicalswift
Copy link
Contributor Author

Closing in favour of #12743 which is a better alternative :-)

sipa added a commit that referenced this pull request Apr 13, 2018
4a6c0e3 Modernize best block mutex/cv/hash variable naming (Pieter Wuille)
45dd135 Fix csBestBlock/cvBlockChange waiting in rpc/mining (Pieter Wuille)

Pull request description:

  This is an alternative to #11694.

  It reintroduces a uint256 variable with the best block hash, protected by csBestBlock, and only updated while holding it.

  Also rename the involved variable to modern guidelines, as there are very few uses.

Tree-SHA512: 826a86c7d3cee7fe49f99f4398ae99e81cb0563197eaeba77306a3ca6072b67cdb932bc35720fc0f99c2a57b218efa029d0b8bdfb240591a629b2e90efa3199d
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Apr 16, 2020
4a6c0e3 Modernize best block mutex/cv/hash variable naming (Pieter Wuille)
45dd135 Fix csBestBlock/cvBlockChange waiting in rpc/mining (Pieter Wuille)

Pull request description:

  This is an alternative to bitcoin#11694.

  It reintroduces a uint256 variable with the best block hash, protected by csBestBlock, and only updated while holding it.

  Also rename the involved variable to modern guidelines, as there are very few uses.

Tree-SHA512: 826a86c7d3cee7fe49f99f4398ae99e81cb0563197eaeba77306a3ca6072b67cdb932bc35720fc0f99c2a57b218efa029d0b8bdfb240591a629b2e90efa3199d
@practicalswift practicalswift deleted the missing-lock-in-getblocktemplate branch April 10, 2021 19:33
gades pushed a commit to cosanta/cosanta-core that referenced this pull request Mar 17, 2022
4a6c0e3 Modernize best block mutex/cv/hash variable naming (Pieter Wuille)
45dd135 Fix csBestBlock/cvBlockChange waiting in rpc/mining (Pieter Wuille)

Pull request description:

  This is an alternative to bitcoin#11694.

  It reintroduces a uint256 variable with the best block hash, protected by csBestBlock, and only updated while holding it.

  Also rename the involved variable to modern guidelines, as there are very few uses.

Tree-SHA512: 826a86c7d3cee7fe49f99f4398ae99e81cb0563197eaeba77306a3ca6072b67cdb932bc35720fc0f99c2a57b218efa029d0b8bdfb240591a629b2e90efa3199d
@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.

7 participants