summaryrefslogtreecommitdiff
path: root/src/lib/ecore_drm
diff options
context:
space:
mode:
authorDuna Oh <duna.oh@samsung.com>2015-12-15 10:02:49 -0500
committerChris Michael <cpmichael@osg.samsung.com>2015-12-15 10:28:39 -0500
commitcb23fd2af2d07c17ae2d6c08a7c87cf8abf45814 (patch)
tree7c875da34053d84745c259ebd17e84fa260144fd /src/lib/ecore_drm
parent7fd907a1322ae251ca171f610dcaf06c700565e7 (diff)
ecore-drm: Fix failure of setting/closing evdev->fd which causes fd leak
Summary: When a input device is plugged in, _cb_open_restricted() is called before creating evdev. So setting fd value on evdev was failed in _cb_open_restricted() and also closing evdev->fd was invalid. Using a eina_hash which has 'path-fd' pairs, we can find fd value after evdev is created. @fix Test Plan: (1) Multiple input devices are connected. Their evdev->fd remains zero or initial value. (2) When one of those devices are plugged out, fd leak would happen. Reviewers: raster, zmike, gwanglim, stefan_schmidt, devilhorns, ManMower Subscribers: cedric, jpeg, Jeon, input.hacker Differential Revision: https://phab.enlightenment.org/D3428
Diffstat (limited to 'src/lib/ecore_drm')
-rw-r--r--src/lib/ecore_drm/ecore_drm.c4
-rw-r--r--src/lib/ecore_drm/ecore_drm_inputs.c39
-rw-r--r--src/lib/ecore_drm/ecore_drm_launcher.c1
-rw-r--r--src/lib/ecore_drm/ecore_drm_private.h2
4 files changed, 31 insertions, 15 deletions
diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c
index 6bbbde05d7..02dd76edbb 100644
--- a/src/lib/ecore_drm/ecore_drm.c
+++ b/src/lib/ecore_drm/ecore_drm.c
@@ -87,6 +87,8 @@ ecore_drm_init(void)
87 /* try to init eeze */ 87 /* try to init eeze */
88 if (!eeze_init()) goto eeze_err; 88 if (!eeze_init()) goto eeze_err;
89 89
90 _ecore_drm_inputs_init();
91
90 ECORE_DRM_EVENT_ACTIVATE = ecore_event_type_new(); 92 ECORE_DRM_EVENT_ACTIVATE = ecore_event_type_new();
91 ECORE_DRM_EVENT_OUTPUT = ecore_event_type_new(); 93 ECORE_DRM_EVENT_OUTPUT = ecore_event_type_new();
92 ECORE_DRM_EVENT_SEAT_ADD = ecore_event_type_new(); 94 ECORE_DRM_EVENT_SEAT_ADD = ecore_event_type_new();
@@ -141,6 +143,8 @@ ecore_drm_shutdown(void)
141 /* shutdown eina */ 143 /* shutdown eina */
142 eina_shutdown(); 144 eina_shutdown();
143 145
146 _ecore_drm_inputs_shutdown();
147
144 /* return init count */ 148 /* return init count */
145 return _ecore_drm_init_count; 149 return _ecore_drm_init_count;
146} 150}
diff --git a/src/lib/ecore_drm/ecore_drm_inputs.c b/src/lib/ecore_drm/ecore_drm_inputs.c
index 75655ec1db..df46b19a7a 100644
--- a/src/lib/ecore_drm/ecore_drm_inputs.c
+++ b/src/lib/ecore_drm/ecore_drm_inputs.c
@@ -5,15 +5,13 @@
5#include "ecore_drm_private.h" 5#include "ecore_drm_private.h"
6 6
7EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1; 7EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1;
8static Eina_Hash *_fd_hash = NULL;
8 9
9/* local functions */ 10/* local functions */
10static int 11static int
11_cb_open_restricted(const char *path, int flags, void *data) 12_cb_open_restricted(const char *path, int flags, void *data)
12{ 13{
13 Ecore_Drm_Input *input; 14 Ecore_Drm_Input *input;
14 Ecore_Drm_Seat *seat;
15 Ecore_Drm_Evdev *edev;
16 Eina_List *l, *ll;
17 int fd = -1; 15 int fd = -1;
18 16
19 if (!(input = data)) return -1; 17 if (!(input = data)) return -1;
@@ -21,18 +19,8 @@ _cb_open_restricted(const char *path, int flags, void *data)
21 /* try to open the device */ 19 /* try to open the device */
22 fd = _ecore_drm_launcher_device_open_no_pending(path, flags); 20 fd = _ecore_drm_launcher_device_open_no_pending(path, flags);
23 if (fd < 0) ERR("Could not open device"); 21 if (fd < 0) ERR("Could not open device");
24 22 if (_fd_hash)
25 EINA_LIST_FOREACH(input->dev->seats, l, seat) 23 eina_hash_add(_fd_hash, path, (void *)(intptr_t)fd);
26 {
27 EINA_LIST_FOREACH(seat->devices, ll, edev)
28 {
29 if (strstr(path, edev->path))
30 {
31 edev->fd = fd;
32 return fd;
33 }
34 }
35 }
36 24
37 return fd; 25 return fd;
38} 26}
@@ -54,6 +42,9 @@ _cb_close_restricted(int fd, void *data)
54 if (edev->fd == fd) 42 if (edev->fd == fd)
55 { 43 {
56 _ecore_drm_launcher_device_close(edev->path, fd); 44 _ecore_drm_launcher_device_close(edev->path, fd);
45
46 /* re-initialize fd after closing */
47 edev->fd = -1;
57 return; 48 return;
58 } 49 }
59 } 50 }
@@ -118,6 +109,8 @@ _device_added(Ecore_Drm_Input *input, struct libinput_device *device)
118 return; 109 return;
119 } 110 }
120 111
112 edev->fd = (int)(intptr_t)eina_hash_find(_fd_hash, edev->path);
113
121 /* append this device to the seat */ 114 /* append this device to the seat */
122 seat->devices = eina_list_append(seat->devices, edev); 115 seat->devices = eina_list_append(seat->devices, edev);
123} 116}
@@ -134,6 +127,9 @@ _device_removed(Ecore_Drm_Input *input EINA_UNUSED, struct libinput_device *devi
134 /* remove this evdev from the seat's list of devices */ 127 /* remove this evdev from the seat's list of devices */
135 edev->seat->devices = eina_list_remove(edev->seat->devices, edev); 128 edev->seat->devices = eina_list_remove(edev->seat->devices, edev);
136 129
130 if (_fd_hash)
131 eina_hash_del_by_key(_fd_hash, edev->path);
132
137 /* tell launcher to release device */ 133 /* tell launcher to release device */
138 _ecore_drm_launcher_device_close(edev->path, edev->fd); 134 _ecore_drm_launcher_device_close(edev->path, edev->fd);
139 135
@@ -345,3 +341,16 @@ ecore_drm_inputs_disable(Ecore_Drm_Input *input)
345 341
346 input->suspended = EINA_TRUE; 342 input->suspended = EINA_TRUE;
347} 343}
344
345void
346_ecore_drm_inputs_init(void)
347{
348 _fd_hash = eina_hash_string_superfast_new(NULL);
349}
350
351void
352_ecore_drm_inputs_shutdown(void)
353{
354 eina_hash_free(_fd_hash);
355 _fd_hash = NULL;
356}
diff --git a/src/lib/ecore_drm/ecore_drm_launcher.c b/src/lib/ecore_drm/ecore_drm_launcher.c
index 2baa550bbf..6ba92ecd2e 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)
167{ 167{
168 if ((logind) && (device)) _ecore_drm_logind_device_close(device); 168 if ((logind) && (device)) _ecore_drm_logind_device_close(device);
169 169
170 if (fd < 0) return;
170 close(fd); 171 close(fd);
171} 172}
diff --git a/src/lib/ecore_drm/ecore_drm_private.h b/src/lib/ecore_drm/ecore_drm_private.h
index aa97a2025f..fbc6bda00e 100644
--- a/src/lib/ecore_drm/ecore_drm_private.h
+++ b/src/lib/ecore_drm/ecore_drm_private.h
@@ -289,4 +289,6 @@ void _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor);
289Eina_Bool _ecore_drm_dbus_session_take(void); 289Eina_Bool _ecore_drm_dbus_session_take(void);
290Eina_Bool _ecore_drm_dbus_session_release(void); 290Eina_Bool _ecore_drm_dbus_session_release(void);
291 291
292void _ecore_drm_inputs_init(void);
293void _ecore_drm_inputs_shutdown(void);
292#endif 294#endif