[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