ecore-drm: Fix failure of setting/closing evdev->fd which causes fd leak 86/53886/6
authorDuna Oh <duna.oh@samsung.com>
Thu, 10 Dec 2015 04:44:12 +0000 (13:44 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Mon, 14 Dec 2015 04:56:31 +0000 (20:56 -0800)
When a input device is plugged in, _cb_open_restricted() is called before creating evdev.
So setting fd value on evdev->fd was failed and also closing evdev->fd was invalid.
This commit has a eina_hash which has 'path-fd' pairs.

Signed-off-by: Duna Oh <duna.oh@samsung.com>
Change-Id: I8e230516edf1ef371158a0ded1569c77c5a27144

src/lib/ecore_drm/ecore_drm.c
src/lib/ecore_drm/ecore_drm_inputs.c
src/lib/ecore_drm/ecore_drm_launcher.c
src/lib/ecore_drm/ecore_drm_private.h

index 0e12d26..2663c5b 100644 (file)
@@ -86,6 +86,8 @@ ecore_drm_init(void)
    /* try to init eeze */
    if (!eeze_init()) goto eeze_err;
 
+   _ecore_drm_inputs_init();
+
    ECORE_DRM_EVENT_ACTIVATE = ecore_event_type_new();
    ECORE_DRM_EVENT_OUTPUT = ecore_event_type_new();
    ECORE_DRM_EVENT_SEAT_ADD = ecore_event_type_new();
@@ -142,6 +144,8 @@ ecore_drm_shutdown(void)
    /* shutdown eina */
    eina_shutdown();
 
+   _ecore_drm_inputs_shutdown();
+
    /* return init count */
    return _ecore_drm_init_count;
 }
index f9fd424..16380b0 100644 (file)
@@ -5,15 +5,13 @@
 #include "ecore_drm_private.h"
 
 EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1;
+static Eina_Hash *_fd_hash = NULL;
 
 /* local functions */
 static int 
 _cb_open_restricted(const char *path, int flags, void *data)
 {
    Ecore_Drm_Input *input;
-   Ecore_Drm_Seat *seat;
-   Ecore_Drm_Evdev *edev;
-   Eina_List *l, *ll;
    int fd = -1;
 
    if (!(input = data)) return -1;
@@ -21,18 +19,8 @@ _cb_open_restricted(const char *path, int flags, void *data)
    /* try to open the device */
    fd = _ecore_drm_launcher_device_open_no_pending(path, flags);
    if (fd < 0) ERR("Could not open device");
-
-   EINA_LIST_FOREACH(input->dev->seats, l, seat)
-     {
-        EINA_LIST_FOREACH(seat->devices, ll, edev)
-          {
-             if (strstr(path, edev->path))
-               {
-                  edev->fd = fd;
-                  return fd;
-               }
-          }
-     }
+   if (_fd_hash)
+     eina_hash_add(_fd_hash, path, (void *)(intptr_t)fd);
 
    return fd;
 }
@@ -54,6 +42,9 @@ _cb_close_restricted(int fd, void *data)
              if (edev->fd == fd)
                {
                   _ecore_drm_launcher_device_close(edev->path, fd);
+
+                  /* re-initialize fd after closing */
+                  edev->fd = -1;
                   return;
                }
           }
@@ -177,6 +168,8 @@ _device_added(Ecore_Drm_Input *input, struct libinput_device *device)
         return;
      }
 
+   edev->fd = (int)(intptr_t)eina_hash_find(_fd_hash, edev->path);
+
    /* append this device to the seat */
    seat->devices = eina_list_append(seat->devices, edev);
 
@@ -226,8 +219,12 @@ _device_removed(Ecore_Drm_Input *input, struct libinput_device *device)
    /* remove this evdev from the seat's list of devices */
    edev->seat->devices = eina_list_remove(edev->seat->devices, edev);
 
+   if (_fd_hash)
+     eina_hash_del_by_key(_fd_hash, edev->path);
+
    /* tell launcher to release device */
-   _ecore_drm_launcher_device_close(edev->path, edev->fd);
+   if (edev->fd >= 0)
+     _ecore_drm_launcher_device_close(edev->path, edev->fd);
 
    /* destroy this evdev */
    _ecore_drm_evdev_device_destroy(edev);
@@ -444,3 +441,16 @@ ecore_drm_seat_evdev_list_get(Ecore_Drm_Seat *seat)
    EINA_SAFETY_ON_NULL_RETURN_VAL(seat, NULL);
    return seat->devices;
 }
+
+void
+_ecore_drm_inputs_init(void)
+{
+  _fd_hash = eina_hash_string_superfast_new(NULL);
+}
+
+void
+_ecore_drm_inputs_shutdown(void)
+{
+   eina_hash_free(_fd_hash);
+   _fd_hash = NULL;
+}
index 2baa550..6ba92ec 100644 (file)
@@ -167,5 +167,6 @@ _ecore_drm_launcher_device_close(const char *device, int fd)
 {
    if ((logind) && (device)) _ecore_drm_logind_device_close(device);
 
+   if (fd < 0) return;
    close(fd);
 }
index 69111ed..3ca67e2 100644 (file)
@@ -302,4 +302,7 @@ Eina_Bool _ecore_drm_dbus_session_take(void);
 Eina_Bool _ecore_drm_dbus_session_release(void);
 
 void _ecore_drm_device_info_send(unsigned int window, Ecore_Drm_Evdev *edev, Eina_Bool flag);
+
+void _ecore_drm_inputs_init(void);
+void _ecore_drm_inputs_shutdown(void);
 #endif