-
Notifications
You must be signed in to change notification settings - Fork 243
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
[spotify] Fix possible deadlock during Spotify scan #1859
Conversation
Good find and nice fix, it looks very clean to me. I didn't review every changed line, but those I did all looked good, so you are welcome to merge. I actually thought a sqlite read wouldn't block a write. Their docs say "Writers merely append new content to the end of the WAL file. Because writers do nothing that would interfere with the actions of readers, writers and readers can run at the same time. However, since there is only one WAL file, there can only be one writer at a time." There are quite a few dbmfi loops like in process_items(), so I wonder if that means there are problems other places. |
By default, owntone uses the "DELETE" journal mode (with a rollback journal). I was thinking that switching to "WAL" (with write-ahead logging) would solve this deadlock. But unfortunately it did not.
The special thing in this case is, that while holding the lock on the mutex an additional write lock on the DB was requested. Here the log for such a DB lock, that will never be unlocked (I added logging of thread name/tid). This is with "WAL" set as journal mode in owntone.conf.
|
Thanks for the clarification, good to hear that it's probably not a general problem. Would it be ok to merge the PR? I'm thinking of making a release soon, since there have been a few good fixes since 28.11, and it would be nice to have this one among them. |
Sure, merged it now :-) |
I ran into a deadlock between the library thread and a worker thread for an artwork request. The deadlock occurs when the library thread does the Spotify scan and an artwork request is made.
During the scan, the library thread holds the lock on the spotify credential mutex.
When there is an artwork request in parallel (e. g. opening the albums page in the web UI), this request is processed in one of the worker threads. Finding artwork opens a DB query to fetch the files (in
process_items
) and steps over the result set. This results in a DB lock held until the query is finalized.The Spotify artwork source now tries to find the artwork in Spotify and blocks because the library thread still holds the lock on the credential mutex.
During the scan in the library thread, it want's now to write into the files table. This will block because the worker/artwork thread holds the DB lock.
The result is a deadlock. The library thread waits for worker/artwork thread to release the DB lock, and the worker/artwork thread waits for the library thread to release the lock on the spotify credentials.
This PR solves it by only holding the lock on the spotify credentials as short as possible. It introduces "credentials_*" functions that should be used instead of directly accessing the
spotify_credentials
global.