connection: Make wl_closure_destroy() close fds of undispatched closures
authorDerek Foreman <derekf@osg.samsung.com>
Wed, 6 Dec 2017 17:22:20 +0000 (11:22 -0600)
committerDaniel Stone <daniels@collabora.com>
Wed, 27 Dec 2017 14:14:31 +0000 (14:14 +0000)
When we have a closure that can't be dispatched for some reason, and it
contains file descriptors, we must close those descriptors to prevent
leaking them.

Previous commits ensure that only FDs belonging to this invocation of
the closure, i.e. not FDs provided by the client for marshalling, nor
FDs which have already been dispatched to either client or server, will
be left in the closure by destroy time.

Signed-off-by: Derek Foreman <derekf@osg.samsung.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
src/connection.c

index 29f565b..e92de79 100644 (file)
@@ -1273,8 +1273,29 @@ wl_closure_print(struct wl_closure *closure, struct wl_object *target, int send)
        fprintf(stderr, ")\n");
 }
 
+static int
+wl_closure_close_fds(struct wl_closure *closure)
+{
+       int i;
+       struct argument_details arg;
+       const char *signature = closure->message->signature;
+
+       for (i = 0; i < closure->count; i++) {
+               signature = get_next_argument(signature, &arg);
+               if (arg.type == 'h' && closure->args[i].h != -1)
+                       close(closure->args[i].h);
+       }
+
+       return 0;
+}
+
 void
 wl_closure_destroy(struct wl_closure *closure)
 {
+       /* wl_closure_destroy has free() semantics */
+       if (!closure)
+               return;
+
+       wl_closure_close_fds(closure);
        free(closure);
 }