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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel