diff options
author | Duna Oh <duna.oh@samsung.com> | 2015-12-15 10:02:49 -0500 |
---|---|---|
committer | Chris Michael <cpmichael@osg.samsung.com> | 2015-12-15 10:28:39 -0500 |
commit | cb23fd2af2d07c17ae2d6c08a7c87cf8abf45814 (patch) | |
tree | 7c875da34053d84745c259ebd17e84fa260144fd /src | |
parent | 7fd907a1322ae251ca171f610dcaf06c700565e7 (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')
-rw-r--r-- | src/lib/ecore_drm/ecore_drm.c | 4 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm_inputs.c | 39 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm_launcher.c | 1 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm_private.h | 2 |
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 | ||
7 | EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1; | 7 | EAPI int ECORE_DRM_EVENT_SEAT_ADD = -1; |
8 | static Eina_Hash *_fd_hash = NULL; | ||
8 | 9 | ||
9 | /* local functions */ | 10 | /* local functions */ |
10 | static int | 11 | static 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 | |||
345 | void | ||
346 | _ecore_drm_inputs_init(void) | ||
347 | { | ||
348 | _fd_hash = eina_hash_string_superfast_new(NULL); | ||
349 | } | ||
350 | |||
351 | void | ||
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); | |||
289 | Eina_Bool _ecore_drm_dbus_session_take(void); | 289 | Eina_Bool _ecore_drm_dbus_session_take(void); |
290 | Eina_Bool _ecore_drm_dbus_session_release(void); | 290 | Eina_Bool _ecore_drm_dbus_session_release(void); |
291 | 291 | ||
292 | void _ecore_drm_inputs_init(void); | ||
293 | void _ecore_drm_inputs_shutdown(void); | ||
292 | #endif | 294 | #endif |