Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pool: Correct racy paymgr processing logic. #396

Merged
merged 1 commit into from
Sep 26, 2023

Conversation

davecgh
Copy link
Member

@davecgh davecgh commented Sep 25, 2023

This corrects the mutex logic in the payment manager that keeps track of whatever or not payments are already being processed.

In particular, the code that is being updated previously checked and set the processing flag under two separate locks of the mutex which could easily result in the first check returning false for two concurrent goroutines followed both both setting it to true and executing which would defeat the purpose of the check.

@davecgh davecgh force-pushed the paymgr_fix_racy_processing_logic branch from 4a28c33 to 077fb27 Compare September 25, 2023 05:46
Copy link
Member

@jholdstock jholdstock left a comment

Choose a reason for hiding this comment

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

Given that payDividends is the only func which accesses the Mutex, I think this can be really simplified. Mutex can just be locked once at the start of the func and then unlocked in a defer.

I don't even think its actually possible for payDividends to be called concurrently because it only has one caller which is in a single goroutine, but we can explore that in another PR.

pool/paymentmgr.go Show resolved Hide resolved
This corrects the mutex logic in the payment manager that keeps track of
whatever or not payments are already being processed.

In particular, the code that is being updated previously checked and set
the processing flag under two separate locks of the mutex which could
easily result in the first check returning false for two concurrent
goroutines followed both both setting it to true and executing which
would defeat the purpose of the check.
@davecgh davecgh force-pushed the paymgr_fix_racy_processing_logic branch from 077fb27 to 69f416b Compare September 26, 2023 08:20
@davecgh
Copy link
Member Author

davecgh commented Sep 26, 2023

Given that payDividends is the only func which accesses the Mutex, I think this can be really simplified. Mutex can just be locked once at the start of the func and then unlocked in a defer.

I originally changed it that way, as I also highly suspect that's true, however I haven't dug into the call paths yet and didn't want to change the semantics until I verify, so I opted for this approach.

@davecgh
Copy link
Member Author

davecgh commented Sep 26, 2023

Looking a little more closely, I see that that payDividends is the result of receiving a message on the paymentCh which itself is sent via processPayments. Then processPayments is used in the chain state config and is invoked as a goroutine from handleChainUpdates for connected blocks.

Since blocks can arrive at any time, and it's executed as a goroutine, it is possible that payDividends is still running. Changing it to a mutex for the entire function would cause it to end up running the entirety of payDividends for every connected block instead of intentionally skipping rapid blocks and processing them as a batch as it does with the current semantics.

@jholdstock jholdstock merged commit f168278 into decred:master Sep 26, 2023
@davecgh davecgh deleted the paymgr_fix_racy_processing_logic branch September 26, 2023 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants