]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
varlink: add exit-on-idle logic for Varlink server
authorLennart Poettering <lennart@poettering.net>
Mon, 25 Sep 2023 13:49:06 +0000 (15:49 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 6 Oct 2023 09:49:38 +0000 (11:49 +0200)
This adds a logic that if enabled ensures sd_event_exit() is called
whenever the varlink connection count hits zero.

This is useful for implementing pure Varlink services (i.e. services
whose only job is to serve Varlink requests), that shall run only as
long as needed, i.e. as long as at least one request is being served.

src/shared/varlink.c
src/shared/varlink.h

index f52c961ce5bf0997cd775a8953604e000f2f9542..6015aed4cf039c679f6a873cd604e8a1bc2cfc6c 100644 (file)
@@ -234,6 +234,8 @@ struct VarlinkServer {
 
         unsigned connections_max;
         unsigned connections_per_uid_max;
+
+        bool exit_on_idle;
 };
 
 static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
@@ -273,6 +275,7 @@ DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(varlink_state, VarlinkState);
         log_debug("%s: " fmt, varlink_server_description(s), ##__VA_ARGS__)
 
 static int varlink_format_queue(Varlink *v);
+static void varlink_server_test_exit_on_idle(VarlinkServer *s);
 
 static const char *varlink_description(Varlink *v) {
         return (v ? v->description : NULL) ?: "varlink";
@@ -1654,6 +1657,7 @@ static void varlink_detach_server(Varlink *v) {
         if (saved_server->disconnect_callback)
                 saved_server->disconnect_callback(saved_server, v, saved_server->userdata);
 
+        varlink_server_test_exit_on_idle(saved_server);
         varlink_server_unref(saved_server);
         varlink_unref(v);
 }
@@ -3098,9 +3102,23 @@ int varlink_server_shutdown(VarlinkServer *s) {
         return 0;
 }
 
+static void varlink_server_test_exit_on_idle(VarlinkServer *s) {
+        assert(s);
+
+        if (s->exit_on_idle && s->event && s->n_connections == 0)
+                (void) sd_event_exit(s->event, 0);
+}
+
+int varlink_server_set_exit_on_idle(VarlinkServer *s, bool b) {
+        assert_return(s, -EINVAL);
+
+        s->exit_on_idle = b;
+        varlink_server_test_exit_on_idle(s);
+        return 0;
+}
+
 static int varlink_server_add_socket_event_source(VarlinkServer *s, VarlinkServerSocket *ss, int64_t priority) {
         _cleanup_(sd_event_source_unrefp) sd_event_source *es = NULL;
-
         int r;
 
         assert(s);
index d49a8510f048fa95c92e35d43dce57b8ce40a537..143d82cabc6066127726071f970630746b1b458a 100644 (file)
@@ -170,6 +170,8 @@ sd_event *varlink_server_get_event(VarlinkServer *v);
 
 int varlink_server_shutdown(VarlinkServer *server);
 
+int varlink_server_set_exit_on_idle(VarlinkServer *s, bool b);
+
 unsigned varlink_server_connections_max(VarlinkServer *s);
 unsigned varlink_server_connections_per_uid_max(VarlinkServer *s);