[PATCH 7/9] core: Protect browse/search/query specs before invoking source operation



So far, specs were destroyed when sources invoke callback with remaining == 0.

This has the drawback that after it, spec is no longer valid, and sources
should avoid to use them. This means that sources must copy spec content if
they want to use them after the callback.

To avoid this problem, before invoking the source operation ref_counter in the
spec is increased, and then decreased after returning. This has the advantage
that when source invokes callback with remaining == 0, spec is not inmediatly
destroyed, but after source returns from the operation. So source is safe to
continue accessing the spec content.

Even more, if source, for any reason, needs to keep the spec even after
returning (could be the spec is in turn wrapped in another structure handled in
an idle function), it can ref() the spec, so it is not destroyed in the return,
but later, when source calls the appropriate unref() function.
---
 src/grl-media-source.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/src/grl-media-source.c b/src/grl-media-source.c
index 8b66005..0d811dd 100644
--- a/src/grl-media-source.c
+++ b/src/grl-media-source.c
@@ -420,7 +420,9 @@ browse_idle (gpointer user_data)
   GrlMediaSourceBrowseSpec *bs = (GrlMediaSourceBrowseSpec *) user_data;
   /* Check if operation was cancelled even before the idle kicked in */
   if (!operation_is_cancelled (bs->source, bs->browse_id)) {
+    grl_media_source_browse_spec_ref (bs);
     GRL_MEDIA_SOURCE_GET_CLASS (bs->source)->browse (bs->source, bs);
+    grl_media_source_browse_spec_unref (bs);
   } else {
     g_debug ("  operation was cancelled");
     bs->callback (bs->source, bs->browse_id, NULL, 0, bs->user_data, NULL);
@@ -435,7 +437,9 @@ search_idle (gpointer user_data)
   GrlMediaSourceSearchSpec *ss = (GrlMediaSourceSearchSpec *) user_data;
   /* Check if operation was cancelled even before the idle kicked in */
   if (!operation_is_cancelled (ss->source, ss->search_id)) {
+    grl_media_source_search_spec_ref (ss);
     GRL_MEDIA_SOURCE_GET_CLASS (ss->source)->search (ss->source, ss);
+    grl_media_source_search_spec_ref (ss);
   } else {
     g_debug ("  operation was cancelled");
     ss->callback (ss->source, ss->search_id, NULL, 0, ss->user_data, NULL);
@@ -449,7 +453,9 @@ query_idle (gpointer user_data)
   g_debug ("query_idle");
   GrlMediaSourceQuerySpec *qs = (GrlMediaSourceQuerySpec *) user_data;
   if (!operation_is_cancelled (qs->source, qs->query_id)) {
+    grl_media_source_query_spec_ref (qs);
     GRL_MEDIA_SOURCE_GET_CLASS (qs->source)->query (qs->source, qs);
+    grl_media_source_query_spec_unref (qs);
   } else {
     g_debug ("  operation was cancelled");
     qs->callback (qs->source, qs->query_id, NULL, 0, qs->user_data, NULL);
-- 
1.7.0.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]