rpc: Add missing cs_main lock in getblocktemplate(…) #11694

pull practicalswift wants to merge 2 commits into bitcoin:master from practicalswift:missing-lock-in-getblocktemplate changing 1 files +7 −1
  1. practicalswift commented at 3:21 pm on November 15, 2017: 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:

    0while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
    
  2. practicalswift commented at 3:23 pm on November 15, 2017: contributor
    @luke-jr @promag, would you mind reviewing this revised version? :-)
  3. in src/rpc/mining.cpp:487 in dbb4a14c7a outdated
    483+            bool keepRunning;
    484+            {
    485+                LOCK(cs_main);
    486+                keepRunning = chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning();
    487+            }
    488+            while (keepRunning)
    


    promag commented at 3:29 pm on November 15, 2017:

    My suggestion is to create a function like:

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

    And here just:

    0while (KeepRunning()) {
    1    ...
    2}
    
  4. promag commented at 3:30 pm on November 15, 2017: member
    Concept ACK.
  5. fanquake added the label RPC/REST/ZMQ on Nov 15, 2017
  6. promag commented at 4:11 pm on November 15, 2017: member
    Restarted travis job.
  7. rpc: Add missing cs_main lock in getblocktemplate(...)
    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())
    ```
    6e65f35f23
  8. practicalswift force-pushed on Nov 15, 2017
  9. luke-jr commented at 4:43 pm on November 15, 2017: member

    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.

  10. practicalswift commented at 4:45 pm on November 15, 2017: contributor
    @promag Now using a lambda to keep it DRY - please re-review :-)
  11. practicalswift commented at 7:08 pm on November 21, 2017: contributor

    @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 :-)

  12. practicalswift commented at 8:32 am on November 30, 2017: contributor
    Pinging @luke-jr :-)
  13. TheBlueMatt commented at 5:58 pm on December 4, 2017: member

    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 6e65f35f23337cf0b284acb2bb2ec038ae83aeca

  14. theuni commented at 6:42 pm on December 4, 2017: member
    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.
  15. TheBlueMatt commented at 6:45 pm on December 4, 2017: member
    @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.
  16. theuni commented at 7:06 pm on December 4, 2017: member
    @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.
  17. practicalswift commented at 7:28 pm on December 4, 2017: contributor

    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.

  18. TheBlueMatt commented at 7:53 pm on December 4, 2017: member
    @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.
  19. theuni commented at 8:15 pm on December 4, 2017: member

    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 6e65f35f23337cf0b284acb2bb2ec038ae83aeca. Looks correct to fix the unguarded access.

  20. practicalswift commented at 8:02 pm on March 14, 2018: contributor
    Any chance of getting this merged? :-)
  21. in src/rpc/mining.cpp:487 in 6e65f35f23 outdated
    483+            auto KeepRunning = [&]() -> bool {
    484+                LOCK(cs_main);
    485+                assert(chainActive.Tip());
    486+                return chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning();
    487+            };
    488+            while (KeepRunning())
    


    promag commented at 9:00 pm on March 14, 2018:

    Sorry but how about plain code?

    0while (IsRPCRunning()) {
    1    {
    2        LOCK(cs_main);
    3        if (chainActive.Tip()->GetBlockHash() != hashWatchedChain) break;
    4    }
    5    ...
    
  22. in src/rpc/mining.cpp:484 in 6e65f35f23 outdated
    478@@ -479,7 +479,12 @@ UniValue getblocktemplate(const JSONRPCRequest& request)
    479             checktxtime = std::chrono::steady_clock::now() + std::chrono::minutes(1);
    480 
    481             WaitableLock lock(csBestBlock);
    482-            while (chainActive.Tip()->GetBlockHash() == hashWatchedChain && IsRPCRunning())
    483+            auto KeepRunning = [&]() -> bool {
    484+                LOCK(cs_main);
    485+                assert(chainActive.Tip());
    


    promag commented at 9:09 pm on March 14, 2018:
    I would drop the assert, otherwise should we add all over where tip is used?
  23. promag commented at 9:11 pm on March 14, 2018: member
    utACK 6e65f35, but I have 2 comments.
  24. Simplify KeepRunning logic a8e661b6b2
  25. practicalswift commented at 10:26 pm on March 14, 2018: contributor
    @promag Good suggestion. Please re-review! @TheBlueMatt @theuni Would you mind re-reviewing in light of the latest commit? :-)
  26. sipa commented at 4:06 am on March 21, 2018: member
    Here is an alternative: #12743
  27. practicalswift commented at 7:09 am on March 21, 2018: contributor
    Closing in favour of #12743 which is a better alternative :-)
  28. practicalswift closed this on Mar 21, 2018

  29. sipa referenced this in commit 4ba6da5574 on Apr 13, 2018
  30. PastaPastaPasta referenced this in commit 1cfba98147 on Apr 12, 2020
  31. PastaPastaPasta referenced this in commit beb57b1333 on Apr 16, 2020
  32. PastaPastaPasta referenced this in commit e480ae9fa8 on Apr 16, 2020
  33. ckti referenced this in commit d5ee70493f on Mar 28, 2021
  34. practicalswift deleted the branch on Apr 10, 2021
  35. gades referenced this in commit f6742a4a7f on Mar 17, 2022
  36. DrahtBot locked this on Aug 18, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-18 18:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me