logind: Send ping to wake us up later
sd_bus_call drains received messages into the receive queue, and peeks for its own return value. It does not dispatch the receive queue. As the socket is drained, the caller will not wake from a poll and have no reason to dispatch libseat. This has gone unnoticed largely due to logind sending an event for every device, making it unlikely that no unread message will be left on the socket. Like we have done for seatd, we fix this by sending a "ping" request to logind if anything is left in our receive queue as reported by sd_bus_get_events. The response to this will wake us up and ensure that dispatch is called.
This commit is contained in:
parent
2eee9aa445
commit
db08fb921f
1 changed files with 47 additions and 1 deletions
|
@ -41,6 +41,7 @@ struct backend_logind {
|
|||
|
||||
bool active;
|
||||
bool initial_setup;
|
||||
bool awaiting_pong;
|
||||
int has_drm;
|
||||
};
|
||||
|
||||
|
@ -67,6 +68,48 @@ static int close_seat(struct libseat *base) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ping_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
(void)ret_error;
|
||||
struct backend_logind *session = userdata;
|
||||
if (sd_bus_message_is_method_error(m, NULL)) {
|
||||
const sd_bus_error *error = sd_bus_message_get_error(m);
|
||||
log_errorf("Ping failed: %s: %s", error->name, error->message);
|
||||
return -1;
|
||||
}
|
||||
session->awaiting_pong = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_ping(struct backend_logind *backend) {
|
||||
int ret = sd_bus_call_method_async(backend->bus, NULL, "org.freedesktop.login1",
|
||||
"/org/freedesktop/login1", "org.freedesktop.DBus.Peer",
|
||||
"Ping", ping_handler, NULL, "");
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_pending_events(struct backend_logind *backend) {
|
||||
if (sd_bus_get_events(backend->bus) <= 0) {
|
||||
return;
|
||||
}
|
||||
if (backend->awaiting_pong) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We have events pending execution, so a dispatch is required.
|
||||
// However, we likely already drained our socket, so there will not be
|
||||
// anything to read. Instead, send a ping request to logind so that the
|
||||
// user will be woken up by its response.
|
||||
int ret = send_ping(backend);
|
||||
if (ret < 0) {
|
||||
log_errorf("Could not send ping message: %s", strerror(-ret));
|
||||
return;
|
||||
}
|
||||
backend->awaiting_pong = true;
|
||||
}
|
||||
|
||||
static int open_device(struct libseat *base, const char *path, int *fd) {
|
||||
struct backend_logind *session = backend_logind_from_libseat_backend(base);
|
||||
|
||||
|
@ -113,9 +156,11 @@ static int open_device(struct libseat *base, const char *path, int *fd) {
|
|||
}
|
||||
|
||||
*fd = tmpfd;
|
||||
|
||||
out:
|
||||
sd_bus_error_free(&error);
|
||||
sd_bus_message_unref(msg);
|
||||
check_pending_events(session);
|
||||
return tmpfd;
|
||||
}
|
||||
|
||||
|
@ -150,7 +195,7 @@ static int close_device(struct libseat *base, int device_id) {
|
|||
|
||||
sd_bus_error_free(&error);
|
||||
sd_bus_message_unref(msg);
|
||||
|
||||
check_pending_events(session);
|
||||
return ret < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
@ -173,6 +218,7 @@ static int switch_session(struct libseat *base, int s) {
|
|||
|
||||
sd_bus_error_free(&error);
|
||||
sd_bus_message_unref(msg);
|
||||
check_pending_events(session);
|
||||
return ret < 0 ? -1 : 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue