Merge branch 'wip/nacho/gregistry' into 'main'

Registry backend fixes

See merge request GNOME/glib!4468
This commit is contained in:
Philip Withnall 2025-02-04 10:40:03 +00:00
commit f7a0e5f13f

View File

@ -179,6 +179,10 @@ typedef struct {
CRITICAL_SECTION *cache_lock; CRITICAL_SECTION *cache_lock;
GNode *cache_root; GNode *cache_root;
/* A lock to protect access to the watch variable */
CRITICAL_SECTION watch_lock;
/* Contains the state of the watching thread. Any access to this variable
* must be done while holding the watch_lock critical section. */
WatchThreadState *watch; WatchThreadState *watch;
} GRegistrySettingsBackend; } GRegistrySettingsBackend;
@ -1734,6 +1738,7 @@ watch_thread_handle_message (WatchThreadState *self)
trace ("watch thread: unsubscribe: freeing node %p, prefix %s, index %i\n", trace ("watch thread: unsubscribe: freeing node %p, prefix %s, index %i\n",
cache_node, self->message.watch.prefix, i); cache_node, self->message.watch.prefix, i);
g_free (self->message.watch.prefix);
if (cache_node != NULL) if (cache_node != NULL)
{ {
@ -1748,7 +1753,6 @@ watch_thread_handle_message (WatchThreadState *self)
} }
_free_watch (self, i, cache_node); _free_watch (self, i, cache_node);
g_free (self->message.watch.prefix);
g_atomic_int_inc (&self->watches_remaining); g_atomic_int_inc (&self->watches_remaining);
break; break;
@ -1762,6 +1766,11 @@ watch_thread_handle_message (WatchThreadState *self)
for (i = 1; i < self->events->len; i++) for (i = 1; i < self->events->len; i++)
_free_watch (self, i, g_ptr_array_index (self->cache_nodes, i)); _free_watch (self, i, g_ptr_array_index (self->cache_nodes, i));
g_ptr_array_unref (self->events);
g_ptr_array_unref (self->handles);
g_ptr_array_unref (self->prefixes);
g_ptr_array_unref (self->cache_nodes);
SetEvent (self->message_received_event); SetEvent (self->message_received_event);
ExitThread (0); ExitThread (0);
} }
@ -1901,6 +1910,7 @@ watch_thread_function (LPVOID parameter)
return -1; return -1;
} }
/* This function assumes you hold the watch lock! */
static gboolean static gboolean
watch_start (GRegistrySettingsBackend *self) watch_start (GRegistrySettingsBackend *self)
{ {
@ -1947,6 +1957,7 @@ fail:
return FALSE; return FALSE;
} }
/* This function assumes you hold the watch lock! */
/* This function assumes you hold the message lock! */ /* This function assumes you hold the message lock! */
static void static void
watch_stop_unlocked (GRegistrySettingsBackend *self) watch_stop_unlocked (GRegistrySettingsBackend *self)
@ -1982,11 +1993,12 @@ watch_stop_unlocked (GRegistrySettingsBackend *self)
self->watch = NULL; self->watch = NULL;
} }
/* This function assumes you hold the watch lock! */
static gboolean static gboolean
watch_add_notify (GRegistrySettingsBackend *self, watch_add_notify (GRegistrySettingsBackend *self,
HANDLE event, HANDLE event,
HKEY hpath, HKEY hpath,
gchar *gsettings_prefix) const gchar *gsettings_prefix)
{ {
WatchThreadState *watch = self->watch; WatchThreadState *watch = self->watch;
GNode *cache_node; GNode *cache_node;
@ -2032,7 +2044,7 @@ watch_add_notify (GRegistrySettingsBackend *self,
watch->message.type = WATCH_THREAD_ADD_WATCH; watch->message.type = WATCH_THREAD_ADD_WATCH;
watch->message.watch.event = event; watch->message.watch.event = event;
watch->message.watch.hpath = hpath; watch->message.watch.hpath = hpath;
watch->message.watch.prefix = gsettings_prefix; watch->message.watch.prefix = g_strdup (gsettings_prefix);
watch->message.watch.cache_node = cache_node; watch->message.watch.cache_node = cache_node;
SetEvent (watch->message_sent_event); SetEvent (watch->message_sent_event);
@ -2055,6 +2067,7 @@ watch_add_notify (GRegistrySettingsBackend *self,
return TRUE; return TRUE;
} }
/* This function assumes you hold the watch lock! */
static void static void
watch_remove_notify (GRegistrySettingsBackend *self, watch_remove_notify (GRegistrySettingsBackend *self,
const gchar *key_name) const gchar *key_name)
@ -2105,12 +2118,17 @@ g_registry_settings_backend_subscribe (GSettingsBackend *backend,
HANDLE event; HANDLE event;
LONG result; LONG result;
EnterCriticalSection (&self->watch_lock);
if (self->watch == NULL && !watch_start (self)) if (self->watch == NULL && !watch_start (self))
{
LeaveCriticalSection (&self->watch_lock);
return; return;
}
if (g_atomic_int_dec_and_test (&self->watch->watches_remaining)) if (g_atomic_int_dec_and_test (&self->watch->watches_remaining))
{ {
g_atomic_int_inc (&self->watch->watches_remaining); g_atomic_int_inc (&self->watch->watches_remaining);
LeaveCriticalSection (&self->watch_lock);
g_warning ("subscribe() failed: only %i different paths may be watched.", MAX_WATCHES); g_warning ("subscribe() failed: only %i different paths may be watched.", MAX_WATCHES);
return; return;
} }
@ -2139,6 +2157,7 @@ g_registry_settings_backend_subscribe (GSettingsBackend *backend,
{ {
g_message_win32_error (result, "gregistrysettingsbackend: Unable to subscribe to key %s.", key_name); g_message_win32_error (result, "gregistrysettingsbackend: Unable to subscribe to key %s.", key_name);
g_atomic_int_inc (&self->watch->watches_remaining); g_atomic_int_inc (&self->watch->watches_remaining);
LeaveCriticalSection (&self->watch_lock);
return; return;
} }
@ -2147,27 +2166,34 @@ g_registry_settings_backend_subscribe (GSettingsBackend *backend,
{ {
g_message_win32_error (result, "gregistrysettingsbackend: CreateEvent failed."); g_message_win32_error (result, "gregistrysettingsbackend: CreateEvent failed.");
g_atomic_int_inc (&self->watch->watches_remaining); g_atomic_int_inc (&self->watch->watches_remaining);
LeaveCriticalSection (&self->watch_lock);
RegCloseKey (hpath); RegCloseKey (hpath);
return; return;
} }
/* The actual watch is added by the thread, which has to re-subscribe each time it /* The actual watch is added by the thread, which has to re-subscribe each time it
* receives a change. */ * receives a change. */
if (!watch_add_notify (self, event, hpath, g_strdup (key_name))) if (!watch_add_notify (self, event, hpath, key_name))
{ {
g_atomic_int_inc (&self->watch->watches_remaining); g_atomic_int_inc (&self->watch->watches_remaining);
RegCloseKey (hpath); RegCloseKey (hpath);
CloseHandle (event); CloseHandle (event);
} }
LeaveCriticalSection (&self->watch_lock);
} }
static void static void
g_registry_settings_backend_unsubscribe (GSettingsBackend *backend, g_registry_settings_backend_unsubscribe (GSettingsBackend *backend,
const char *key_name) const char *key_name)
{ {
GRegistrySettingsBackend *self = G_REGISTRY_SETTINGS_BACKEND (backend);
trace ("unsubscribe: %s.\n", key_name); trace ("unsubscribe: %s.\n", key_name);
watch_remove_notify (G_REGISTRY_SETTINGS_BACKEND (backend), key_name); EnterCriticalSection (&self->watch_lock);
watch_remove_notify (self, key_name);
LeaveCriticalSection (&self->watch_lock);
} }
/******************************************************************************** /********************************************************************************
@ -2191,6 +2217,7 @@ g_registry_settings_backend_finalize (GObject *object)
EnterCriticalSection (self->watch->message_lock); EnterCriticalSection (self->watch->message_lock);
watch_stop_unlocked (self); watch_stop_unlocked (self);
} }
DeleteCriticalSection (&self->watch_lock);
DeleteCriticalSection (self->cache_lock); DeleteCriticalSection (self->cache_lock);
g_slice_free (CRITICAL_SECTION, self->cache_lock); g_slice_free (CRITICAL_SECTION, self->cache_lock);
@ -2341,6 +2368,7 @@ g_registry_settings_backend_init (GRegistrySettingsBackend *self)
InitializeCriticalSection (self->cache_lock); InitializeCriticalSection (self->cache_lock);
self->watch = NULL; self->watch = NULL;
InitializeCriticalSection (&self->watch_lock);
} }
/** /**