[gvfs] mtp: fix storage-list-related race condition between STORE_ADDED event handler and do_query_info()
- From: Philip Langdale <philipl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gvfs] mtp: fix storage-list-related race condition between STORE_ADDED event handler and do_query_info()
- Date: Sat, 16 Aug 2014 01:30:52 +0000 (UTC)
commit bb1862582a93f6f73e251f7b156d15817c27e16a
Author: Rok Mandeljc <rok mandeljc gmail com>
Date: Thu Aug 14 00:16:08 2014 +0200
mtp: fix storage-list-related race condition between STORE_ADDED event handler and do_query_info()
The LIBMTP_Get_Storage() call in STORE_ADDED event handler needs
to be called with backend mutex held, otherwise it races with
iteration over storages list in do_query_info() as the latter
attempts to retrieve information about storage.
The issues occur when several stores are added at the same time,
because after a store is added, Nautilus immediately queries it
for info.
Also, backend reference should probably also be released in cases
when LIBMTP_Get_Storage() fails.
Signed-off-by: Rok Mandeljc <rok mandeljc gmail com>
daemon/gvfsbackendmtp.c | 41 +++++++++++++++++++++++++++--------------
1 files changed, 27 insertions(+), 14 deletions(-)
---
diff --git a/daemon/gvfsbackendmtp.c b/daemon/gvfsbackendmtp.c
index 5abe7f9..2c52622 100644
--- a/daemon/gvfsbackendmtp.c
+++ b/daemon/gvfsbackendmtp.c
@@ -642,26 +642,28 @@ check_event (gpointer user_data)
LIBMTP_mtpdevice_t *device = backend->device;
LIBMTP_devicestorage_t *storage;
+ g_mutex_lock (&backend->mutex);
+
int ret = LIBMTP_Get_Storage (device, LIBMTP_STORAGE_SORTBY_NOTSORTED);
if (ret != 0) {
LIBMTP_Dump_Errorstack (device);
LIBMTP_Clear_Errorstack (device);
- break;
- }
- g_mutex_lock (&backend->mutex);
- for (storage = device->storage; storage != 0; storage = storage->next) {
- if (storage->id == param1) {
- char *storage_name = create_storage_name (storage);
- char *path = g_build_filename ("/", storage_name, NULL);
- g_free (storage_name);
-
- add_cache_entry (G_VFS_BACKEND_MTP (backend),
- path,
- storage->id,
- -1);
- g_hash_table_foreach (backend->monitors, emit_create_event, path);
+ } else {
+ for (storage = device->storage; storage != 0; storage = storage->next) {
+ if (storage->id == param1) {
+ char *storage_name = create_storage_name (storage);
+ char *path = g_build_filename ("/", storage_name, NULL);
+ g_free (storage_name);
+
+ add_cache_entry (G_VFS_BACKEND_MTP (backend),
+ path,
+ storage->id,
+ -1);
+ g_hash_table_foreach (backend->monitors, emit_create_event, path);
+ }
}
}
+
g_mutex_unlock (&backend->mutex);
g_object_unref (backend);
break;
@@ -1369,12 +1371,23 @@ do_query_info (GVfsBackend *backend,
}
LIBMTP_devicestorage_t *storage;
+ gboolean found = FALSE;
for (storage = device->storage; storage != 0; storage = storage->next) {
if (storage->id == entry->storage) {
DEBUG ("(I) found storage %X\n", storage->id);
+ found = TRUE;
get_storage_info (storage, info);
+ break;
}
}
+
+ if (!found) {
+ DEBUG ("(W) storage %X not found?!\n", entry->storage);
+ g_vfs_job_failed_literal (G_VFS_JOB (job),
+ G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+ _("Directory doesn't exist"));
+ goto exit;
+ }
} else {
CacheEntry *entry = get_cache_entry (G_VFS_BACKEND_MTP (backend),
filename);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]