Commit 61219e26 authored by Allison Karlitskaya's avatar Allison Karlitskaya

GSettingsBackend: make signal dispatch threadsafe

This commit fixes up a few race conditions in the GSettingsBackend, mostly with
respect to change notifications occuring at the same time as the last reference
count on a GSettings is dropped.  With GDBus feeding us our incoming signals in
a separate thread, this is something that could easily happen.
parent 4967b6d2
......@@ -199,11 +199,11 @@ g_delayed_settings_backend_revert (GDelayedSettingsBackend *delayed)
/* change notification */
static void
delayed_backend_changed (GSettingsBackend *backend,
GObject *target,
const gchar *key,
gpointer origin_tag,
gpointer user_data)
gpointer origin_tag)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (user_data);
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
if (origin_tag != delayed->priv)
g_settings_backend_changed (G_SETTINGS_BACKEND (delayed),
......@@ -212,12 +212,12 @@ delayed_backend_changed (GSettingsBackend *backend,
static void
delayed_backend_keys_changed (GSettingsBackend *backend,
GObject *target,
const gchar *path,
const gchar * const *items,
gpointer origin_tag,
gpointer user_data)
gpointer origin_tag)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (user_data);
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
if (origin_tag != delayed->priv)
g_settings_backend_keys_changed (G_SETTINGS_BACKEND (delayed),
......@@ -225,12 +225,12 @@ delayed_backend_keys_changed (GSettingsBackend *backend,
}
static void
delayed_backend_path_changed (GSettingsBackend *backend,
const gchar *path,
gpointer origin_tag,
gpointer user_data)
delayed_backend_path_changed (GSettingsBackend *backend,
GObject *target,
const gchar *path,
gpointer origin_tag)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (user_data);
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
if (origin_tag != delayed->priv)
g_settings_backend_path_changed (G_SETTINGS_BACKEND (delayed),
......@@ -239,10 +239,10 @@ delayed_backend_path_changed (GSettingsBackend *backend,
static void
delayed_backend_writable_changed (GSettingsBackend *backend,
const gchar *key,
gpointer user_data)
GObject *target,
const gchar *key)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (user_data);
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
if (g_tree_lookup (delayed->priv->delayed, key) &&
!g_settings_backend_get_writable (delayed->priv->backend, key))
......@@ -285,10 +285,10 @@ check_prefix (gpointer key,
static void
delayed_backend_path_writable_changed (GSettingsBackend *backend,
const gchar *path,
gpointer user_data)
GObject *target,
const gchar *path)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (user_data);
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (target);
gsize n_keys;
n_keys = g_tree_nnodes (delayed->priv->delayed);
......@@ -323,7 +323,6 @@ g_delayed_settings_backend_finalize (GObject *object)
{
GDelayedSettingsBackend *delayed = G_DELAYED_SETTINGS_BACKEND (object);
g_settings_backend_unwatch (delayed->priv->backend, delayed);
g_object_unref (delayed->priv->backend);
}
......@@ -367,13 +366,12 @@ g_delayed_settings_backend_new (GSettingsBackend *backend,
delayed->priv->backend = g_object_ref (backend);
delayed->priv->owner = owner;
g_settings_backend_watch (delayed->priv->backend, NULL,
g_settings_backend_watch (delayed->priv->backend, G_OBJECT (delayed), NULL,
delayed_backend_changed,
delayed_backend_path_changed,
delayed_backend_keys_changed,
delayed_backend_writable_changed,
delayed_backend_path_writable_changed,
delayed);
delayed_backend_path_writable_changed);
return delayed;
}
......@@ -224,11 +224,11 @@ g_settings_real_writable_change_event (GSettings *settings,
static void
settings_backend_changed (GSettingsBackend *backend,
GObject *target,
const gchar *key,
gpointer origin_tag,
gpointer user_data)
gpointer origin_tag)
{
GSettings *settings = G_SETTINGS (user_data);
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
gint i;
......@@ -249,11 +249,11 @@ settings_backend_changed (GSettingsBackend *backend,
static void
settings_backend_path_changed (GSettingsBackend *backend,
GObject *target,
const gchar *path,
gpointer origin_tag,
gpointer user_data)
gpointer origin_tag)
{
GSettings *settings = G_SETTINGS (user_data);
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
g_assert (settings->priv->backend == backend);
......@@ -265,12 +265,12 @@ settings_backend_path_changed (GSettingsBackend *backend,
static void
settings_backend_keys_changed (GSettingsBackend *backend,
GObject *target,
const gchar *path,
const gchar * const *items,
gpointer origin_tag,
gpointer user_data)
gpointer origin_tag)
{
GSettings *settings = G_SETTINGS (user_data);
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
gint i;
......@@ -309,10 +309,10 @@ settings_backend_keys_changed (GSettingsBackend *backend,
static void
settings_backend_writable_changed (GSettingsBackend *backend,
const gchar *key,
gpointer user_data)
GObject *target,
const gchar *key)
{
GSettings *settings = G_SETTINGS (user_data);
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
gint i;
......@@ -328,10 +328,10 @@ settings_backend_writable_changed (GSettingsBackend *backend,
static void
settings_backend_path_writable_changed (GSettingsBackend *backend,
const gchar *path,
gpointer user_data)
GObject *target,
const gchar *path)
{
GSettings *settings = G_SETTINGS (user_data);
GSettings *settings = G_SETTINGS (target);
gboolean ignore_this;
g_assert (settings->priv->backend == backend);
......@@ -365,14 +365,13 @@ g_settings_constructed (GObject *object)
}
settings->priv->backend = g_settings_backend_get_with_context (settings->priv->context);
g_settings_backend_watch (settings->priv->backend,
g_settings_backend_watch (settings->priv->backend, G_OBJECT (settings),
settings->priv->main_context,
settings_backend_changed,
settings_backend_path_changed,
settings_backend_keys_changed,
settings_backend_writable_changed,
settings_backend_path_writable_changed,
settings);
settings_backend_path_writable_changed);
g_settings_backend_subscribe (settings->priv->backend,
settings->priv->path);
}
......@@ -412,18 +411,17 @@ g_settings_delay (GSettings *settings)
settings->priv->delayed =
g_delayed_settings_backend_new (settings->priv->backend, settings);
g_settings_backend_unwatch (settings->priv->backend, settings);
g_settings_backend_unwatch (settings->priv->backend, G_OBJECT (settings));
g_object_unref (settings->priv->backend);
settings->priv->backend = G_SETTINGS_BACKEND (settings->priv->delayed);
g_settings_backend_watch (settings->priv->backend,
g_settings_backend_watch (settings->priv->backend, G_OBJECT (settings),
settings->priv->main_context,
settings_backend_changed,
settings_backend_path_changed,
settings_backend_keys_changed,
settings_backend_writable_changed,
settings_backend_path_writable_changed,
settings);
settings_backend_path_writable_changed);
}
/**
......@@ -546,7 +544,6 @@ g_settings_finalize (GObject *object)
{
GSettings *settings = G_SETTINGS (object);
g_settings_backend_unwatch (settings->priv->backend, settings);
g_settings_backend_unsubscribe (settings->priv->backend,
settings->priv->path);
g_main_context_unref (settings->priv->main_context);
......
This diff is collapsed.
......@@ -27,37 +27,37 @@
#include "gsettingsbackend.h"
typedef void (*GSettingsBackendChangedFunc) (GSettingsBackend *backend,
GObject *target,
const gchar *key,
gpointer origin_tag,
gpointer user_data);
gpointer origin_tag);
typedef void (*GSettingsBackendPathChangedFunc) (GSettingsBackend *backend,
GObject *target,
const gchar *path,
gpointer origin_tag,
gpointer user_data);
gpointer origin_tag);
typedef void (*GSettingsBackendKeysChangedFunc) (GSettingsBackend *backend,
GObject *target,
const gchar *prefix,
const gchar * const *names,
gpointer origin_tag,
gpointer user_data);
gpointer origin_tag);
typedef void (*GSettingsBackendWritableChangedFunc) (GSettingsBackend *backend,
const gchar *key,
gpointer user_data);
GObject *target,
const gchar *key);
typedef void (*GSettingsBackendPathWritableChangedFunc) (GSettingsBackend *backend,
const gchar *path,
gpointer user_data);
GObject *target,
const gchar *path);
G_GNUC_INTERNAL
void g_settings_backend_watch (GSettingsBackend *backend,
GObject *target,
GMainContext *context,
GSettingsBackendChangedFunc changed,
GSettingsBackendPathChangedFunc path_changed,
GSettingsBackendKeysChangedFunc keys_changed,
GSettingsBackendWritableChangedFunc writable_changed,
GSettingsBackendPathWritableChangedFunc path_writable_changed,
gpointer user_data);
GSettingsBackendPathWritableChangedFunc path_writable_changed);
G_GNUC_INTERNAL
void g_settings_backend_unwatch (GSettingsBackend *backend,
gpointer user_data);
GObject *target);
G_GNUC_INTERNAL
gboolean g_settings_backend_supports_context (const gchar *context);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment