diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2012-10-18 17:17:47 -0400 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2012-10-18 17:34:21 -0400 |
commit | 94971592e200274da9d6c910aff75e77c10d8415 (patch) | |
tree | e8b5488d9d49b98f24b6952e026e2007ff6759d3 /src | |
parent | 06bde7666c64c7fa408a320a33ca100f51fc8c1d (diff) | |
download | nautilus-94971592e200274da9d6c910aff75e77c10d8415.tar.gz |
shell-provider: make the provider more robust to cancellation
Don't assume there's only one engine running at the time, and avoid
requiring state from the global app singleton in search callbacks.
This fixes a crash where we would dereference NULL in the hits-added
callback, since we would access it through the global app object, and
self->active_search was previously cleared on cancellation.
https://bugzilla.gnome.org/show_bug.cgi?id=686168
Diffstat (limited to 'src')
-rw-r--r-- | src/nautilus-shell-search-provider.c | 81 |
1 files changed, 38 insertions, 43 deletions
diff --git a/src/nautilus-shell-search-provider.c b/src/nautilus-shell-search-provider.c index c8f02636d..55f795e67 100644 --- a/src/nautilus-shell-search-provider.c +++ b/src/nautilus-shell-search-provider.c @@ -40,7 +40,12 @@ #define SEARCH_PROVIDER_INACTIVITY_TIMEOUT 12000 /* milliseconds */ +typedef GApplicationClass NautilusShellSearchProviderAppClass; +typedef struct _NautilusShellSearchProviderApp NautilusShellSearchProviderApp; + typedef struct { + NautilusShellSearchProviderApp *self; + NautilusSearchEngine *engine; NautilusQuery *query; @@ -50,7 +55,7 @@ typedef struct { gint64 start_time; } PendingSearch; -typedef struct { +struct _NautilusShellSearchProviderApp { GApplication parent; guint name_owner_id; @@ -63,9 +68,7 @@ typedef struct { NautilusBookmarkList *bookmarks; GVolumeMonitor *volumes; -} NautilusShellSearchProviderApp; - -typedef GApplicationClass NautilusShellSearchProviderAppClass; +}; GType nautilus_shell_search_provider_app_get_type (void); @@ -142,30 +145,24 @@ pending_search_free (PendingSearch *search) } static void -finish_current_search (NautilusShellSearchProviderApp *self, - GDBusMethodInvocation *invocation, - GVariant *result) +pending_search_finish (PendingSearch *search, + GDBusMethodInvocation *invocation, + GVariant *result) { - g_dbus_method_invocation_return_value (invocation, result); - - if (self->current_search != NULL) { - g_application_release (G_APPLICATION (self)); + NautilusShellSearchProviderApp *self = search->self; - pending_search_free (self->current_search); + if (search == self->current_search) self->current_search = NULL; - } + + g_application_release (G_APPLICATION (self)); + pending_search_free (search); } static void cancel_current_search (NautilusShellSearchProviderApp *self) { - PendingSearch *search = self->current_search; - - if (search == NULL) - return; - - nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (search->engine)); - finish_current_search (self, search->invocation, g_variant_new ("(as)", NULL)); + if (self->current_search != NULL) + nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (self->current_search->engine)); } static void @@ -174,8 +171,7 @@ search_hits_added_cb (NautilusSearchEngine *engine, gpointer user_data) { - NautilusShellSearchProviderApp *self = user_data; - PendingSearch *search = self->current_search; + PendingSearch *search = user_data; GList *l; NautilusSearchHit *hit; const gchar *hit_uri; @@ -217,8 +213,7 @@ static void search_finished_cb (NautilusSearchEngine *engine, gpointer user_data) { - NautilusShellSearchProviderApp *self = user_data; - PendingSearch *search = self->current_search; + PendingSearch *search = user_data; GList *hits, *l; NautilusSearchHit *hit; GVariantBuilder builder; @@ -239,7 +234,7 @@ search_finished_cb (NautilusSearchEngine *engine, } g_list_free (hits); - finish_current_search (self, search->invocation, + pending_search_finish (search, search->invocation, g_variant_new ("(as)", &builder)); } @@ -252,7 +247,8 @@ search_error_cb (NautilusSearchEngine *engine, PendingSearch *search = self->current_search; g_debug ("*** Search engine search error"); - finish_current_search (self, search->invocation, g_variant_new ("(as)", NULL)); + pending_search_finish (search, search->invocation, + g_variant_new ("(as)", NULL)); } typedef struct { @@ -282,7 +278,7 @@ search_hit_candidate_new (const gchar *uri, } static void -search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) +search_add_volumes_and_bookmarks (PendingSearch *search) { NautilusSearchHit *hit; NautilusBookmark *bookmark; @@ -300,9 +296,9 @@ search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) candidates = NULL; /* first add bookmarks */ - length = nautilus_bookmark_list_length (self->bookmarks); + length = nautilus_bookmark_list_length (search->self->bookmarks); for (idx = 0; idx < length; idx++) { - bookmark = nautilus_bookmark_list_item_at (self->bookmarks, idx); + bookmark = nautilus_bookmark_list_item_at (search->self->bookmarks, idx); name = nautilus_bookmark_get_name (bookmark); if (name == NULL) @@ -329,7 +325,7 @@ search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) mounts_to_check = NULL; /* first check all connected drives */ - drives = g_volume_monitor_get_connected_drives (self->volumes); + drives = g_volume_monitor_get_connected_drives (search->self->volumes); for (l = drives; l != NULL; l = l->next) { drive = l->data; volumes = g_drive_get_volumes (drive); @@ -347,7 +343,7 @@ search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) g_list_free_full (drives, g_object_unref); /* then volumes that don't have a drive */ - volumes = g_volume_monitor_get_volumes (self->volumes); + volumes = g_volume_monitor_get_volumes (search->self->volumes); for (l = volumes; l != NULL; l = l->next) { volume = l->data; drive = g_volume_get_drive (volume); @@ -363,7 +359,7 @@ search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) g_list_free_full (volumes, g_object_unref); /* then mounts that have no volume */ - mounts = g_volume_monitor_get_mounts (self->volumes); + mounts = g_volume_monitor_get_mounts (search->self->volumes); for (l = mounts; l != NULL; l = l->next) { mount = l->data; @@ -401,14 +397,14 @@ search_add_volumes_and_bookmarks (NautilusShellSearchProviderApp *self) for (l = candidates; l != NULL; l = l->next) { candidate = l->data; - match = nautilus_query_matches_string (self->current_search->query, + match = nautilus_query_matches_string (search->query, candidate->string_for_compare); if (match > -1) { hit = nautilus_search_hit_new (candidate->uri); nautilus_search_hit_set_fts_rank (hit, match); - nautilus_search_hit_compute_scores (hit, self->current_search->query); - g_hash_table_replace (self->current_search->hits, g_strdup (candidate->uri), hit); + nautilus_search_hit_compute_scores (hit, search->query); + g_hash_table_replace (search->hits, g_strdup (candidate->uri), hit); } } g_list_free_full (candidates, (GDestroyNotify) search_hit_candidate_free); @@ -423,14 +419,12 @@ execute_search (NautilusShellSearchProviderApp *self, NautilusQuery *query; PendingSearch *pending_search; - if (self->current_search != NULL) - cancel_current_search (self); + cancel_current_search (self); /* don't attempt searches for a single character */ if (g_strv_length (terms) == 1 && g_utf8_strlen (terms[0], -1) == 1) { - finish_current_search (self, invocation, - g_variant_new ("(as)", NULL)); + g_dbus_method_invocation_return_value (invocation, g_variant_new ("(as)", NULL)); return; } @@ -448,18 +442,19 @@ execute_search (NautilusShellSearchProviderApp *self, pending_search->query = query; pending_search->engine = nautilus_search_engine_new (); pending_search->start_time = g_get_monotonic_time (); + pending_search->self = self; g_signal_connect (pending_search->engine, "hits-added", - G_CALLBACK (search_hits_added_cb), self); + G_CALLBACK (search_hits_added_cb), pending_search); g_signal_connect (pending_search->engine, "finished", - G_CALLBACK (search_finished_cb), self); + G_CALLBACK (search_finished_cb), pending_search); g_signal_connect (pending_search->engine, "error", - G_CALLBACK (search_error_cb), self); + G_CALLBACK (search_error_cb), pending_search); self->current_search = pending_search; g_application_hold (G_APPLICATION (self)); - search_add_volumes_and_bookmarks (self); + search_add_volumes_and_bookmarks (pending_search); /* start searching */ g_debug ("*** Search engine search started"); |