forked from enlightenment/efl
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
This commit is contained in:
parent
7fd907a132
commit
cb23fd2af2
|
@ -87,6 +87,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();
|
||||
|
@ -141,6 +143,8 @@ ecore_drm_shutdown(void)
|
|||
/* shutdown eina */
|
||||
eina_shutdown();
|
||||
|
||||
_ecore_drm_inputs_shutdown();
|
||||
|
||||
/* return init count */
|
||||
return _ecore_drm_init_count;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -118,6 +109,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);
|
||||
}
|
||||
|
@ -134,6 +127,9 @@ _device_removed(Ecore_Drm_Input *input EINA_UNUSED, struct libinput_device *devi
|
|||
/* 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);
|
||||
|
||||
|
@ -345,3 +341,16 @@ ecore_drm_inputs_disable(Ecore_Drm_Input *input)
|
|||
|
||||
input->suspended = EINA_TRUE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -289,4 +289,6 @@ void _ecore_drm_dbus_device_release(uint32_t major, uint32_t minor);
|
|||
Eina_Bool _ecore_drm_dbus_session_take(void);
|
||||
Eina_Bool _ecore_drm_dbus_session_release(void);
|
||||
|
||||
void _ecore_drm_inputs_init(void);
|
||||
void _ecore_drm_inputs_shutdown(void);
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue