[PATCH BlueZ v5 5/6] obexd: Support sd_login_monitor_get_timeout()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The documentation for sd_login_monitor_get_timeout() implies the API
may need to be checked after some time, even if no events have been
received via the fd.

In practice, the implementation has always returned a dummy value,
and changing it now would cause enough breakage in other projects
to make it unlikely to ever happen.

Add a handler for that case, even though it can't currently
happen in the real world.

The API assumes we call poll() directly, so in theory it could change
the timeout based on some event that doesn't trigger a callback
(e.g. sending a signal to the service).  It's hard to see how we'd
handle that without running a poll() in a separate thread,
which would be a lot of complexity for an untestable edge case.
Don't try to handle that problem.

Cc: Pauli Virtanen <pav@xxxxxx>
Signed-off-by: Andrew Sayers <kernel.org@xxxxxxxxxxxxxxx>
---
 obexd/src/logind.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/obexd/src/logind.c b/obexd/src/logind.c
index ff2bf3219..a0eb62b1e 100644
--- a/obexd/src/logind.c
+++ b/obexd/src/logind.c
@@ -30,6 +30,7 @@ static int uid;
 static gboolean active = FALSE;
 static gboolean monitoring_enabled = TRUE;
 static guint event_source;
+static guint timeout_source;
 
 struct callback_pair {
 	logind_init_cb init_cb;
@@ -82,8 +83,11 @@ static int update(void)
 	return res;
 }
 
+static gboolean timeout_handler(gpointer user_data);
+
 static int check_event(void)
 {
+	uint64_t timeout_usec;
 	int res;
 
 	res = sd_login_monitor_flush(monitor);
@@ -95,6 +99,25 @@ static int check_event(void)
 	if (res < 0)
 		return res;
 
+	res = sd_login_monitor_get_timeout(monitor, &timeout_usec);
+	if (res < 0)
+		return res;
+
+	if (timeout_usec != (uint64_t)-1) {
+		uint64_t time_usec;
+		struct timespec ts;
+		guint interval;
+
+		res = clock_gettime(CLOCK_MONOTONIC, &ts);
+		if (res < 0)
+			return -errno;
+		time_usec = (uint64_t) ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+		if (time_usec > timeout_usec)
+			return check_event();
+		interval = (timeout_usec - time_usec + 999) / 1000;
+		timeout_source = g_timeout_add(interval, timeout_handler, NULL);
+	}
+
 	return 0;
 }
 
@@ -104,6 +127,11 @@ static gboolean event_handler(GIOChannel *source, GIOCondition condition,
 {
 	int res;
 
+	if (timeout_source) {
+		g_source_remove(timeout_source);
+		timeout_source = 0;
+	}
+
 	res = check_event();
 	if (res) {
 		error("%s: %s", __func__, strerror(-res));
@@ -113,6 +141,17 @@ static gboolean event_handler(GIOChannel *source, GIOCondition condition,
 	return TRUE;
 }
 
+static gboolean timeout_handler(gpointer user_data)
+{
+	int res;
+
+	res = check_event();
+	if (res)
+		error("%s: %s", __func__, strerror(-res));
+
+	return FALSE;
+}
+
 static int logind_init(void)
 {
 	GIOChannel *channel;
@@ -173,6 +212,10 @@ static void logind_exit(void)
 		g_source_remove(event_source);
 		event_source = 0;
 	}
+	if (timeout_source) {
+		g_source_remove(timeout_source);
+		timeout_source = 0;
+	}
 	sd_login_monitor_unref(monitor);
 }
 
-- 
2.49.0





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux