summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Kukkonen <jussi.kukkonen@intel.com>2014-01-19 01:50:02 +0200
committerJussi Kukkonen <jussi.kukkonen@intel.com>2014-01-21 15:00:45 +0200
commitbf151a712020250461ceb1f43e7bcf949466800c (patch)
tree7bf4ecdea87f0e70154109795fd9e5aeb5b5ef8d
parent17442e3876fa85a861b5624d51a9211fef15112d (diff)
downloadgupnp-bf151a712020250461ceb1f43e7bcf949466800c.tar.gz
Survive ServiceProxy callback-list changes from callbacks
Make notify-callback code more robust, so that removing a notify-callback from a notify-callback works. https://bugzilla.gnome.org/show_bug.cgi?id=690400
-rw-r--r--libgupnp/gupnp-service-proxy.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/libgupnp/gupnp-service-proxy.c b/libgupnp/gupnp-service-proxy.c
index 3272723..ec76277 100644
--- a/libgupnp/gupnp-service-proxy.c
+++ b/libgupnp/gupnp-service-proxy.c
@@ -97,6 +97,7 @@ typedef struct {
GType type;
GList *callbacks;
+ GList *next_emit;
} NotifyData;
typedef struct {
@@ -1602,6 +1603,7 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy *proxy,
data->type = type;
data->callbacks = NULL;
+ data->next_emit = NULL;
g_hash_table_insert (proxy->priv->notify_hash,
g_strdup (variable),
@@ -1627,6 +1629,9 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy *proxy,
data->callbacks = g_list_append (data->callbacks, callback_data);
+ if (data->next_emit == NULL)
+ data->next_emit = g_list_last (data->callbacks);
+
return TRUE;
}
@@ -1639,9 +1644,10 @@ gupnp_service_proxy_add_notify (GUPnPServiceProxy *proxy,
*
* Cancels the variable change notification for @callback and @user_data.
*
- * This function must not be called directly or indirectly from a
- * #GUPnPServiceProxyNotifyCallback associated with this service proxy, even
- * if it is for another variable.
+ * In version 20.9 and earlier this function must not be called directly
+ * or indirectly from a #GUPnPServiceProxyNotifyCallback associated with
+ * this service proxy, even if it is for another variable. In later
+ * versions such calls are allowed.
*
* Return value: %TRUE on success.
**/
@@ -1681,6 +1687,9 @@ gupnp_service_proxy_remove_notify (GUPnPServiceProxy *proxy,
/* Gotcha! */
g_slice_free (CallbackData, callback_data);
+ if (data->next_emit == l)
+ data->next_emit = data->next_emit->next;
+
data->callbacks =
g_list_delete_link (data->callbacks, l);
if (data->callbacks == NULL) {
@@ -1722,11 +1731,13 @@ emit_notification (GUPnPServiceProxy *proxy,
return;
}
- /* Call callbacks */
- for (l = data->callbacks; l; l = l->next) {
+ /* Call callbacks. Note that data->next_emit may change if
+ * callback calls remove_notify() or add_notify() */
+ for (l = data->callbacks; l; l = data->next_emit) {
CallbackData *callback_data;
callback_data = l->data;
+ data->next_emit = l->next;
callback_data->callback (proxy,
(const char *) var_node->name,