mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2026-04-22 06:00:39 +02:00
eis: fix an error when the seat is removed twice
Previous sequence reproducible with the eis-demo-server and ei-demo-client: - ctrl+c the client - eis client dispatch fails with an rc < 0 due to the socket being closed - eis calls eis_client_disconnect() which calls eis_seat_removed() - that triggers an event for `SEAT_UNBIND` - seat is set to REMOVE - eis-demo-server gets the `SEAT_UNBIND` event and (correctly) calls eis_seat_remove() since it doesn't know the client is disconnected yet. That is due to the library unwinding the state transparently. Fix this by splitting out the calls: eis_drop_seat() is the internally used one that sets it to a new state of REMOVED_INTERNALLY, and then eis_seat_remove merely updates the state. Fixes #10 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
6f3a62f5d2
commit
7a91f27d42
3 changed files with 31 additions and 11 deletions
|
|
@ -190,8 +190,7 @@ eis_client_disconnect(struct eis_client *client)
|
|||
{
|
||||
struct eis_seat *s;
|
||||
list_for_each_safe(s, &client->seats, link) {
|
||||
eis_seat_unbind(s);
|
||||
eis_seat_remove(s);
|
||||
eis_seat_drop(s);
|
||||
}
|
||||
}
|
||||
eis_queue_disconnect_event(client);
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ enum eis_seat_state {
|
|||
EIS_SEAT_STATE_ADDED,
|
||||
EIS_SEAT_STATE_BOUND,
|
||||
EIS_SEAT_STATE_UNBOUND,
|
||||
EIS_SEAT_STATE_REMOVED_INTERNALLY, /* Removed internally but eis_seat_remove() may be called */
|
||||
EIS_SEAT_STATE_REMOVED, /* Removed but still waiting for some devices to be removed */
|
||||
EIS_SEAT_STATE_DEAD, /* Removed from our list */
|
||||
};
|
||||
|
|
@ -251,6 +252,9 @@ eis_seat_bind(struct eis_seat *seat, uint32_t cap);
|
|||
void
|
||||
eis_seat_unbind(struct eis_seat *seat);
|
||||
|
||||
void
|
||||
eis_seat_drop(struct eis_seat *seat);
|
||||
|
||||
struct eis *
|
||||
eis_device_get_context(struct eis_device *device);
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ eis_seat_add(struct eis_seat *seat)
|
|||
case EIS_SEAT_STATE_BOUND:
|
||||
case EIS_SEAT_STATE_UNBOUND:
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
case EIS_SEAT_STATE_REMOVED_INTERNALLY:
|
||||
case EIS_SEAT_STATE_DEAD:
|
||||
log_bug_client(eis_client_get_context(client),
|
||||
"%s: seat already added/removed/dead\n", __func__);
|
||||
|
|
@ -112,6 +113,7 @@ eis_seat_bind(struct eis_seat *seat, uint32_t caps)
|
|||
case EIS_SEAT_STATE_BOUND:
|
||||
case EIS_SEAT_STATE_UNBOUND:
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
case EIS_SEAT_STATE_REMOVED_INTERNALLY:
|
||||
case EIS_SEAT_STATE_DEAD:
|
||||
log_bug_client(eis_client_get_context(client),
|
||||
"%s: seat cannot be bound\n", __func__);
|
||||
|
|
@ -134,6 +136,7 @@ eis_seat_unbind(struct eis_seat *seat)
|
|||
case EIS_SEAT_STATE_PENDING:
|
||||
case EIS_SEAT_STATE_UNBOUND:
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
case EIS_SEAT_STATE_REMOVED_INTERNALLY:
|
||||
case EIS_SEAT_STATE_DEAD:
|
||||
log_bug_client(eis_client_get_context(client),
|
||||
"%s: seat cannot be unbound\n", __func__);
|
||||
|
|
@ -144,16 +147,39 @@ eis_seat_unbind(struct eis_seat *seat)
|
|||
eis_queue_seat_unbind_event(seat);
|
||||
}
|
||||
|
||||
void
|
||||
eis_seat_drop(struct eis_seat *seat)
|
||||
{
|
||||
if (seat->state == EIS_SEAT_STATE_BOUND)
|
||||
eis_seat_unbind(seat);
|
||||
|
||||
struct eis_device *d;
|
||||
list_for_each_safe(d, &seat->devices, link) {
|
||||
eis_device_remove(d);
|
||||
}
|
||||
|
||||
eis_client_remove_seat(eis_seat_get_client(seat), seat);
|
||||
list_remove(&seat->link);
|
||||
seat->state = EIS_SEAT_STATE_REMOVED_INTERNALLY;
|
||||
eis_seat_unref(seat);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
eis_seat_remove(struct eis_seat *seat)
|
||||
{
|
||||
struct eis_client *client = eis_seat_get_client(seat);
|
||||
_unref_(eis_seat) *s = eis_seat_ref(seat);
|
||||
|
||||
switch (seat->state) {
|
||||
case EIS_SEAT_STATE_PENDING:
|
||||
case EIS_SEAT_STATE_ADDED:
|
||||
case EIS_SEAT_STATE_BOUND:
|
||||
case EIS_SEAT_STATE_UNBOUND:
|
||||
eis_seat_drop(s);
|
||||
s->state = EIS_SEAT_STATE_REMOVED;
|
||||
break;
|
||||
case EIS_SEAT_STATE_REMOVED_INTERNALLY:
|
||||
s->state = EIS_SEAT_STATE_REMOVED;
|
||||
break;
|
||||
case EIS_SEAT_STATE_REMOVED:
|
||||
case EIS_SEAT_STATE_DEAD:
|
||||
|
|
@ -162,15 +188,6 @@ eis_seat_remove(struct eis_seat *seat)
|
|||
return;
|
||||
}
|
||||
|
||||
struct eis_device *d;
|
||||
list_for_each_safe(d, &seat->devices, link) {
|
||||
eis_device_remove(d);
|
||||
}
|
||||
|
||||
eis_client_remove_seat(eis_seat_get_client(seat), seat);
|
||||
seat->state = EIS_SEAT_STATE_REMOVED;
|
||||
list_remove(&seat->link);
|
||||
eis_seat_unref(seat);
|
||||
}
|
||||
|
||||
_public_ void
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue