Call g_source_remove when removing fd form context 83/180083/4
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Thu, 24 May 2018 11:51:24 +0000 (13:51 +0200)
committerlokilee73 <changjoo.lee@samsung.com>
Mon, 28 May 2018 06:35:53 +0000 (15:35 +0900)
Not removed glib source can cause trouble in mainloop and possible
leaks. This commit makes sure the source is removed when no longer
needed.

Change-Id: I346f9f17c1de75775b24063c3389d164e5aa6e47
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
src/usb_host.c

index 768566ef371041f1d68c355d009a0d3a5b1bffa2..fc38a323553770ec05157c26e6c10a8bc0ab6571 100644 (file)
@@ -405,9 +405,14 @@ static gboolean usb_host_poll_cb(GIOChannel *source, GIOCondition condition, gpo
        return TRUE;
 }
 
+struct gio_channel_wrap {
+       GIOChannel *ch;
+       guint source_tag;
+};
+
 static int add_fd_watch(int fd, short events, void *user_data)
 {
-       GIOChannel *ch;
+       struct gio_channel_wrap *ch;
        usb_host_context_h ctx = user_data;
        GIOCondition condition = 0;
 
@@ -416,13 +421,20 @@ static int add_fd_watch(int fd, short events, void *user_data)
        if (events & POLLOUT)
                condition |= G_IO_OUT;
 
-       ch = g_io_channel_unix_new(fd);
+       ch = malloc(sizeof(*ch));
        if (!ch) {
+               _E("malloc() failed"); //LCOV_EXCL_LINE
+               return USB_HOST_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
+       }
+
+       ch->ch = g_io_channel_unix_new(fd);
+       if (!ch->ch) {
                _E("Failed to create gio channel"); //LCOV_EXCL_LINE
+               free(ch); //LCOV_EXCL_LINE
                return USB_HOST_ERROR_OUT_OF_MEMORY;
        }
 
-       g_io_add_watch(ch, condition, usb_host_poll_cb, ctx);
+       ch->source_tag = g_io_add_watch(ch->ch, condition, usb_host_poll_cb, ctx);
 
        pthread_mutex_lock(&ctx->channel_list_lock);
        _I("added fd %d to poll", fd);
@@ -439,7 +451,7 @@ static void fd_added_cb(int fd, short events, void *user_data)
 
 static void fd_removed_cb(int fd, void *user_data)
 {
-       GIOChannel *ch;
+       struct gio_channel_wrap *ch;
        usb_host_context_h ctx = user_data;
        GList *l, *next;
        int rfd;
@@ -449,10 +461,12 @@ static void fd_removed_cb(int fd, void *user_data)
        while (l != NULL) {
                ch = l->data;
                next = l->next;
-               rfd = g_io_channel_unix_get_fd(ch);
+               rfd = g_io_channel_unix_get_fd(ch->ch);
                if (fd == rfd) {
-                       g_io_channel_unref(ch);
+                       g_source_remove(ch->source_tag);
+                       g_io_channel_unref(ch->ch);
                        ctx->gio_channels = g_list_delete_link(ctx->gio_channels, l);
+                       free(ch);
                }
 
                l = next;
@@ -470,7 +484,7 @@ int usb_host_create(usb_host_context_h *ctx)
        struct usb_host_context_s *_ctx;
        const struct libusb_pollfd **pollfds = NULL;
        GList *l, *next;
-       GIOChannel *ch;
+       struct gio_channel_wrap *ch;
 
        if (!usb_host_feature_enabled())
                return USB_HOST_ERROR_NOT_SUPPORTED;
@@ -531,8 +545,9 @@ free_ctx:
        while (l != NULL) {
                ch = l->data;
                next = l->next;
-               g_io_channel_unref(ch);
+               g_io_channel_unref(ch->ch);
                l = next;
+               free(ch);
        }
 
        g_list_free(_ctx->gio_channels);
@@ -544,8 +559,9 @@ out:
 
 int usb_host_destroy(usb_host_context_h context)
 {
-       GIOChannel *ch;
+       struct gio_channel_wrap *ch;
        GList *l, *next;
+       int fd;
 
        if (!usb_host_feature_enabled())
                return USB_HOST_ERROR_NOT_SUPPORTED;
@@ -559,8 +575,12 @@ int usb_host_destroy(usb_host_context_h context)
        while (l != NULL) {
                ch = l->data;
                next = l->next;
-               g_io_channel_unref(ch);
+               fd = g_io_channel_unix_get_fd(ch->ch);
+               g_source_remove(ch->source_tag);
+               g_io_channel_unref(ch->ch);
                l = next;
+               free(ch);
+               _I("removed fd %d", fd);
        }
 
        g_list_free(context->gio_channels);