From aedc8d40763b059b996bdfc95d4974ac2f793b63 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Fri, 13 Nov 2015 23:30:27 +0100
Subject: server: Introduce refcounting for registry notifications.

---
 server/registry.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/server/registry.c b/server/registry.c
index ead9749..5c70b8d 100644
--- a/server/registry.c
+++ b/server/registry.c
@@ -58,6 +58,7 @@ struct notify_event
 
 struct notify
 {
+    unsigned int      refcount; /* number of references */
     struct list       entry;    /* entry in list of notifications */
     struct list       events;   /* list of events to set when changing this key */
     int               subtree;  /* true if subtree notification */
@@ -311,6 +312,14 @@ static void do_notification( struct key *key, struct notify *notify, int del )
 {
     void *ptr;
 
+    if (del)
+        list_remove( &notify->entry );
+    else
+    {
+        assert( notify->refcount < INT_MAX );
+        notify->refcount++;
+    }
+
     while ((ptr = list_head( &notify->events )))
     {
         struct notify_event *notify_event = LIST_ENTRY( ptr, struct notify_event, entry );
@@ -320,11 +329,9 @@ static void do_notification( struct key *key, struct notify *notify, int del )
         free( notify_event );
     }
 
-    if (del)
-    {
-        list_remove( &notify->entry );
+    assert( notify->refcount );
+    if (!--notify->refcount)
         free( notify );
-    }
 }
 
 static inline struct notify *find_notify( struct key *key, struct process *process, obj_handle_t hkey )
@@ -2282,6 +2289,7 @@ DECL_HANDLER(set_registry_notification)
             notify = find_notify( key, current->process, req->hkey );
             if (!notify && (notify = mem_alloc( sizeof(*notify) )))
             {
+                notify->refcount = 1;
                 list_init( &notify->events );
                 notify->subtree = req->subtree;
                 notify->filter  = req->filter;
-- 
2.6.2

