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

MultiWallet struct should be tread safe #252

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

LasTshaMAN
Copy link

(likely) Resolves #865

This PR adds a mutexes around MultiWallet.wallets and MultiWallet.badWallets maps to prevent races during concurrent access.

Haven't tested these changes myself, though.

@dreacot
Copy link
Contributor

dreacot commented May 25, 2022

@itswisdomagain please could you take a look this

Copy link
Contributor

@itswisdomagain itswisdomagain left a comment

Choose a reason for hiding this comment

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

Will review again after this. As a rule of thumb, if an operation won't take long, don't make a copy of the wallets map or lock and unlock the mutex more than once.

multiwallet.go Outdated
Comment on lines 128 to 136
mw.badWallets[wallet.ID] = wallet
mw.badWalletsUpdate(wallet.ID, wallet)
log.Warnf("Ignored wallet load error for wallet %d (%s)", wallet.ID, wallet.Name)
} else {
mw.wallets[wallet.ID] = wallet
mw.walletsUpdate(wallet.ID, wallet)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's safe to updates the maps directly here without locking the mutex as they won't be accessed concurrently during this initialization. Alternatively, you can lock the mutexes before the for loop and unlock after, rather than locking/unlocking for each insert.

multiwallet.go Outdated
@@ -155,7 +160,7 @@ func (mw *MultiWallet) Shutdown() {
mw.CancelRescan()
mw.CancelSync()

for _, wallet := range mw.wallets {
for _, wallet := range mw.walletsReadCopy() {
Copy link
Contributor

Choose a reason for hiding this comment

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

During shutdown, don't use a copy of the wallets. Lock the mutexes here and access the mw.wallets map directly. Basically, any other operation that needs access to the map should wait for the shutting down to complete. Additionally, before unlocking the mutex, clear the map.

multiwallet.go Outdated
@@ -275,7 +280,7 @@ func (mw *MultiWallet) OpenWallets(startupPassphrase []byte) error {
return err
}

for _, wallet := range mw.wallets {
for _, wallet := range mw.walletsReadCopy() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment above applies here. Keep the mutex locked and prevent any other access to the map until the wallets are all opened.

multiwallet.go Outdated
@@ -429,6 +434,60 @@ func (mw *MultiWallet) LinkExistingWallet(walletName, walletDataDir, originalPub
})
}

// walletsReadCopy is concurrently-safe way to read from mw.wallets map.
func (mw *MultiWallet) walletsReadCopy() map[int]*Wallet {
result := make(map[int]*Wallet, len(mw.wallets))
Copy link
Contributor

Choose a reason for hiding this comment

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

Lock before reading len(mw.wallets). Also applies to the badWalletsReadyCopy method.

Copy link
Author

Choose a reason for hiding this comment

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

missed this one, good catch

@LasTshaMAN
Copy link
Author

yeah, like I've mentioned above my reasoning was "to find and fix the issue in all places, without missing any, and then we can optimize on top of that"

image

I'll address each comment soon

@LasTshaMAN
Copy link
Author

Cleaned up a bit and addressed all the comments above.

@LasTshaMAN
Copy link
Author

@itswisdomagain pls take a look when you can ^

@LasTshaMAN LasTshaMAN force-pushed the multi-wallet-struct-should-be-tread-safe branch from 9a4e59d to 3a5d4ce Compare August 24, 2022 10:20
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.

app crashes while deleting a wallet
3 participants