When a directory is removed from the library during a scan, the scan continues
until complete. This change cancels the scan immediately, unblocking the watcher
thread, then signals the watcher to remove the directory.
A second issue occurs when a previously scanned device is removed during a
scan. All remaining files will be marked as deleted. This change mitigates
this issue, but a timing hole still remains here.
On Linux systems, failure to watch a path may be caused by the limit set in
/proc/sys/fs/inotify/max_user_watches. This can be demonstrated by creating
a directory with a large number of empty subdirectories and adding that test
directory as a library.
Check that a file is readable before adding a watch. If adding the watch fails,
report the error to the user only once. Only add the path to subdir_mapping_
if watch succeeds.
A LibraryBackend may be deleted while an associated LibraryModel object is using
it. An example is an async query running while a connected device is removed.
To prevent this, use a share pointer for the LibraryBackend.
This fixes one case where LibraryBackend is used after deletion. However, the
raw pointer is still passed around in several other places. These should be
evaluated on a case-by-case basis to insure that circular depencencies aren't
introduced.
When unmounting a device, the ConnectedDevice object is destroyed. The
FileSystemDevice destructor waits on its worker thread. If a scan is in
progress, this will block until completion.
There is an existing Stop method in the LibraryWatcher class that is intended to
stop long running operations. To fix, or at least significantly shorten this
hang, we'll call this before waiting for the thread to exit. Also add a
stop_requested check in the cover art scan.
In addition, add a call to Stop in the Library destructor, which has a similar
usage.