mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-08-22 07:01:30 +00:00
[client] evdev: split teardown into stop and free phases
evdev_stop was never called, and calling it revealed unsafe teardown: the device list was freed before the thread was joined, a zero epoll descriptor was mistaken for a valid one, and the device loops walked past the end of the array through a sentinel that does not exist. Join the thread in evdev_stop and defer the rest to the new evdev_free. The display server grab hooks route into evdev until its event thread is joined, so the device state must stay valid until the display server has been freed; evdev_free then restores the hooks and releases the state.
This commit is contained in:
committed by
Geoffrey McRae
parent
c66a974f1d
commit
75f7d614a7
@@ -31,10 +31,16 @@ void evdev_earlyInit(void);
|
|||||||
bool evdev_start(void);
|
bool evdev_start(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* stop the evdev layer
|
* join the evdev thread; device state stays valid for callbacks
|
||||||
*/
|
*/
|
||||||
void evdev_stop(void);
|
void evdev_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* restore the display server hooks and free the device state; only
|
||||||
|
* call once display server callbacks have stopped
|
||||||
|
*/
|
||||||
|
void evdev_free(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* grab the keyboard for exclusive access
|
* grab the keyboard for exclusive access
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ struct EvdevState
|
|||||||
pending;
|
pending;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct EvdevState state = {};
|
static struct EvdevState state = { .epoll = -1 };
|
||||||
|
|
||||||
static struct Option options[] =
|
static struct Option options[] =
|
||||||
{
|
{
|
||||||
@@ -351,31 +351,51 @@ bool evdev_start(void)
|
|||||||
|
|
||||||
void evdev_stop(void)
|
void evdev_stop(void)
|
||||||
{
|
{
|
||||||
|
if (state.thread)
|
||||||
|
{
|
||||||
|
lgJoinThread(state.thread, NULL);
|
||||||
|
state.thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void evdev_free(void)
|
||||||
|
{
|
||||||
|
evdev_stop();
|
||||||
|
|
||||||
|
// restore the display server grab methods
|
||||||
|
if (state.dsGrabKeyboard)
|
||||||
|
{
|
||||||
|
g_state.ds->grabKeyboard = state.dsGrabKeyboard;
|
||||||
|
g_state.ds->ungrabKeyboard = state.dsUngrabKeyboard;
|
||||||
|
state.dsGrabKeyboard = NULL;
|
||||||
|
state.dsUngrabKeyboard = NULL;
|
||||||
|
}
|
||||||
|
state.grabbed = false;
|
||||||
|
|
||||||
|
// the thread and grab callbacks reference the device state
|
||||||
if (state.deviceList)
|
if (state.deviceList)
|
||||||
{
|
{
|
||||||
free(state.deviceList);
|
free(state.deviceList);
|
||||||
state.deviceList = NULL;
|
state.deviceList = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.thread)
|
|
||||||
{
|
|
||||||
lgJoinThread(state.thread, NULL);
|
|
||||||
state.thread = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.epoll >= 0)
|
if (state.epoll >= 0)
|
||||||
{
|
{
|
||||||
close(state.epoll);
|
close(state.epoll);
|
||||||
state.epoll = 0;
|
state.epoll = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(EvdevDevice * device = state.devices; device->path; ++device)
|
if (state.devices)
|
||||||
{
|
{
|
||||||
if (device->fd <= 0)
|
for(int i = 0; i < state.deviceCount; ++i)
|
||||||
continue;
|
{
|
||||||
|
EvdevDevice * device = &state.devices[i];
|
||||||
|
if (device->fd > 0)
|
||||||
close(device->fd);
|
close(device->fd);
|
||||||
device->fd = 0;
|
}
|
||||||
|
free(state.devices);
|
||||||
|
state.devices = NULL;
|
||||||
|
state.deviceCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,8 +415,9 @@ void evdev_grabKeyboard(void)
|
|||||||
|
|
||||||
// state.dsGrabKeyboard();
|
// state.dsGrabKeyboard();
|
||||||
|
|
||||||
for(EvdevDevice * device = state.devices; device->path; ++device)
|
for(int i = 0; i < state.deviceCount; ++i)
|
||||||
{
|
{
|
||||||
|
EvdevDevice * device = &state.devices[i];
|
||||||
if (device->fd > 0)
|
if (device->fd > 0)
|
||||||
evdev_grabDevice(device);
|
evdev_grabDevice(device);
|
||||||
}
|
}
|
||||||
@@ -418,8 +439,9 @@ void evdev_ungrabKeyboard(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(EvdevDevice * device = state.devices; device->path; ++device)
|
for(int i = 0; i < state.deviceCount; ++i)
|
||||||
{
|
{
|
||||||
|
EvdevDevice * device = &state.devices[i];
|
||||||
if (device->fd <= 0 || !device->grabbed)
|
if (device->fd <= 0 || !device->grabbed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user