From a81fd0f2f57ae6b71703a9a76922f9ff13fdb9ab Mon Sep 17 00:00:00 2001 From: Duna Oh Date: Thu, 10 Dec 2015 13:44:12 +0900 Subject: [PATCH] ecore-drm: Fix failure of setting/closing evdev->fd which causes fd leak 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 Change-Id: I8e230516edf1ef371158a0ded1569c77c5a27144 --- src/lib/ecore_drm/ecore_drm.c | 4 ++++ src/lib/ecore_drm/ecore_drm_inputs.c | 42 +++++++++++++++++++++------------- src/lib/ecore_drm/ecore_drm_launcher.c | 1 + src/lib/ecore_drm/ecore_drm_private.h | 3 +++ 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c index 0e12d26..2663c5b 100644 --- a/src/lib/ecore_drm/ecore_drm.c +++ b/src/lib/ecore_drm/ecore_drm.c @@ -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; } diff --git a/src/lib/ecore_drm/ecore_drm_inputs.c b/src/lib/ecore_drm/ecore_drm_inputs.c index f9fd424..16380b0 100644 --- a/src/lib/ecore_drm/ecore_drm_inputs.c +++ b/src/lib/ecore_drm/ecore_drm_inputs.c @@ -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; +} diff --git a/src/lib/ecore_drm/ecore_drm_launcher.c b/src/lib/ecore_drm/ecore_drm_launcher.c index 2baa550..6ba92ec 100644 --- a/src/lib/ecore_drm/ecore_drm_launcher.c +++ b/src/lib/ecore_drm/ecore_drm_launcher.c @@ -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); } diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h index 69111ed..3ca67e2 100644 --- a/src/lib/ecore_drm/ecore_drm_private.h +++ b/src/lib/ecore_drm/ecore_drm_private.h @@ -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 -- 2.7.4