[systemd-devel] [PATCH 2/2] [POC] networkd: port to glib main loop

Tom Gundersen teg at jklm.no
Wed Aug 20 08:28:39 PDT 2014


Just a test-case for the sd_event hooks, not to be merged (obviously).

This introduces (MIT licensed) glib-event-glue.[ch], which is meant to
end up as an example people could copy. Will probably need to find a home
for it though.
---
 Makefile.am                    |  15 ++++-
 src/network/glib-event-glue.c  | 138 +++++++++++++++++++++++++++++++++++++++++
 src/network/glib-event-glue.h  |  30 +++++++++
 src/network/networkd-manager.c |  11 ++++
 src/network/networkd.c         |   9 ++-
 src/network/networkd.h         |   2 +
 6 files changed, 197 insertions(+), 8 deletions(-)
 create mode 100644 src/network/glib-event-glue.c
 create mode 100644 src/network/glib-event-glue.h

diff --git a/Makefile.am b/Makefile.am
index 4028112..3f3a57a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4951,11 +4951,17 @@ systemd_networkd_LDADD = \
 	libsystemd-networkd-core.la \
 	libsystemd-capability.la
 
+systemd_networkd_CFLAGS = \
+	$(GLIB_CFLAGS) \
+	-fPIC
+
 noinst_LTLIBRARIES += \
 	libsystemd-networkd-core.la
 
 libsystemd_networkd_core_la_CFLAGS = \
-	$(AM_CFLAGS)
+	$(AM_CFLAGS) \
+	$(GLIB_CFLAGS) \
+	-fPIC
 
 libsystemd_networkd_core_la_SOURCES = \
 	src/libsystemd-network/network-internal.h \
@@ -4988,7 +4994,9 @@ libsystemd_networkd_core_la_SOURCES = \
 	src/network/networkd-address.c \
 	src/network/networkd-route.c \
 	src/network/networkd-manager.c \
-	src/network/networkd-address-pool.c
+	src/network/networkd-address-pool.c \
+	src/network/glib-event-glue.h \
+	src/network/glib-event-glue.c
 
 nodist_libsystemd_networkd_core_la_SOURCES = \
 	src/network/networkd-network-gperf.c \
@@ -4999,7 +5007,8 @@ libsystemd_networkd_core_la_LIBADD = \
 	libsystemd-internal.la \
 	libsystemd-network.la \
 	libsystemd-label.la \
-	libsystemd-shared.la
+	libsystemd-shared.la \
+	$(GLIB_LIBS)
 
 rootlibexec_PROGRAMS += \
 	systemd-networkd-wait-online
diff --git a/src/network/glib-event-glue.c b/src/network/glib-event-glue.c
new file mode 100644
index 0000000..db47b80
--- /dev/null
+++ b/src/network/glib-event-glue.c
@@ -0,0 +1,138 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  Copyright 2014 Tom Gundersen
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "glib-event-glue.h"
+
+typedef struct SDEventSource {
+        GSource source;
+        GPollFD pollfd;
+        sd_event *event;
+} SDEventSource;
+
+static gboolean event_prepare(GSource *source, gint *timeout_) {
+        sd_event *event;
+        int r;
+
+        assert(source);
+
+        event = ((SDEventSource *)source)->event;
+
+        r = sd_event_prepare(event);
+        if (r > 0)
+                return TRUE;
+        else
+                return FALSE;
+}
+
+static gboolean event_check(GSource *source) {
+        sd_event *event;
+        int r;
+
+        assert(source);
+
+        event = ((SDEventSource *)source)->event;
+
+        r = sd_event_wait(event, 0);
+        if (r > 0)
+                return TRUE;
+        else
+                return FALSE;
+}
+
+static gboolean event_dispatch(GSource *source, GSourceFunc callback,
+                         gpointer user_data) {
+        sd_event *event;
+        int r;
+
+        assert(source);
+
+        event = ((SDEventSource *)source)->event;
+
+        r = sd_event_dispatch(event);
+        if (r < 0)
+                return G_SOURCE_REMOVE;
+        else
+                return G_SOURCE_CONTINUE;
+}
+
+static void event_finalize(GSource *source) {
+        assert(source);
+
+        sd_event_unref(((SDEventSource *)source)->event);
+}
+
+static int event_quit(sd_event_source *source, void *userdata) {
+        GMainLoop *loop = userdata;
+
+        assert(loop);
+
+        g_main_loop_quit(loop);
+
+        return 1;
+}
+
+static GSourceFuncs event_funcs = {
+        .prepare = event_prepare,
+        .check = event_check,
+        .dispatch = event_dispatch,
+        .finalize = event_finalize,
+};
+
+int attach_sd_event_to_g_main_loop(GMainLoop *loop, sd_event *event) {
+        GSource *source = NULL;
+        SDEventSource *event_source;
+        int r;
+
+        assert(loop);
+        assert(event);
+
+        source = g_source_new(&event_funcs, sizeof(SDEventSource));
+        if (!source)
+                return -ENOMEM;
+        g_source_set_name(source, "sd-event");
+
+        event_source = (SDEventSource *)source;
+
+        event_source->event = sd_event_ref(event);
+        event_source->pollfd.fd = sd_event_get_fd(event);
+        event_source->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+
+        g_source_add_poll(source, &event_source->pollfd);
+
+        g_source_attach(source, g_main_loop_get_context(loop));
+
+        r = sd_event_add_exit(event, NULL, event_quit, loop);
+        if (r < 0) {
+                g_source_unref(source);
+                return r;
+        }
+
+        return 0;
+}
diff --git a/src/network/glib-event-glue.h b/src/network/glib-event-glue.h
new file mode 100644
index 0000000..380d791
--- /dev/null
+++ b/src/network/glib-event-glue.h
@@ -0,0 +1,30 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  Copyright 2014 Tom Gundersen
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include <glib.h>
+#include <sd-event.h>
+
+int attach_sd_event_to_g_main_loop(GMainLoop *loop, sd_event *event);
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index f2fe5d5..384ce72 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -34,6 +34,8 @@
 #include "mkdir.h"
 #include "virt.h"
 
+#include "glib-event-glue.h"
+
 #include "sd-rtnl.h"
 
 const char* const network_dirs[] = {
@@ -88,6 +90,14 @@ int manager_new(Manager **ret) {
         if (r < 0)
                 return r;
 
+        m->loop = g_main_loop_new(NULL, true);
+        if (!m->loop)
+                return -ENOMEM;
+
+        r = attach_sd_event_to_g_main_loop(m->loop, m->event);
+        if (r < 0)
+                return r;
+
         sd_event_set_watchdog(m->event, true);
 
         sd_event_add_signal(m->event, NULL, SIGTERM, NULL, NULL);
@@ -149,6 +159,7 @@ void manager_free(Manager *m) {
         sd_event_source_unref(m->sigterm_event_source);
         sd_event_source_unref(m->sigint_event_source);
         sd_event_unref(m->event);
+        g_main_loop_unref(m->loop);
 
         while ((link = hashmap_first(m->links)))
                 link_unref(link);
diff --git a/src/network/networkd.c b/src/network/networkd.c
index 665f4c4..6564cc1 100644
--- a/src/network/networkd.c
+++ b/src/network/networkd.c
@@ -19,6 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <glib.h>
+
 #include "capability.h"
 #include "sd-event.h"
 #include "sd-daemon.h"
@@ -117,11 +119,8 @@ int main(int argc, char *argv[]) {
                   "READY=1\n"
                   "STATUS=Processing requests...");
 
-        r = sd_event_loop(m->event);
-        if (r < 0) {
-                log_error("Event loop failed: %s", strerror(-r));
-                goto out;
-        }
+        g_main_loop_run(m->loop);
+        r = 0;
 
 out:
         sd_notify(false,
diff --git a/src/network/networkd.h b/src/network/networkd.h
index ab5df1a..0c4b1a4 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -22,6 +22,7 @@
 #pragma once
 
 #include <arpa/inet.h>
+#include <glib.h>
 
 #include "sd-event.h"
 #include "sd-rtnl.h"
@@ -168,6 +169,7 @@ struct AddressPool {
 struct Manager {
         sd_rtnl *rtnl;
         sd_event *event;
+        GMainLoop *loop;
         sd_bus *bus;
         struct udev *udev;
         struct udev_monitor *udev_monitor;
-- 
1.9.3



More information about the systemd-devel mailing list