Integrate mainloop with glib 59/159559/11
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Wed, 8 Nov 2017 09:52:54 +0000 (10:52 +0100)
committerPaweł Szewczyk <p.szewczyk@samsung.com>
Fri, 24 Nov 2017 15:35:32 +0000 (16:35 +0100)
Change-Id: If5079eefdfd3d65638b63c718254cf0878359e2f
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
Makefile.am
configure.ac
packaging/faultd.spec
src/core/faultd-glib.c [new file with mode: 0644]
src/core/faultd-glib.h [new file with mode: 0644]
src/faultd.c

index 87bceee978fb0ec9d1bc1f33a8d2126a1a50b92e..2786f092acbe98b8407e8cc41e8ed563975497c0 100644 (file)
@@ -44,6 +44,7 @@ AM_CFLAGS = \
        -D_GNU_SOURCE=1 \
        -fPIE \
        -rdynamic \
+       $(GLIB_CFLAGS) \
        -D"FAULTD_MODNAME_T=$(call name_fix,$(modname))"
 
 AM_LDFLAGS = \
@@ -103,6 +104,10 @@ faultd_SOURCES = \
     src/database/database_nop.c \
     src/util/systemd_dbus.c
 
+if GLIB_MAINLOOP
+faultd_SOURCES += src/core/faultd-glib.c
+endif
+
 # Add here source files of modules that must have ability to enable/disable during build
 # This variable is parsed by Autoconf
 EXTRA_faultd_SOURCES = \
@@ -151,7 +156,7 @@ system_reboot_action_la_SOURCES = src/action/system_reboot.c
 system_reboot_to_recovery_action_la_SOURCES = src/action/system_reboot_to_recovery.c
 service_recover_action_la_SOURCES = src/action/service_recover.c
 
-faultd_LDADD = $(LIBSYSTEMD_LIBS) $(JSON_C_LIBS)
+faultd_LDADD = $(LIBSYSTEMD_LIBS) $(GLIB_LIBS) $(JSON_C_LIBS)
 
 %.pc: %.pc.in Makefile
        $(SED_PROCESS)
index 95b230ef5004cb950fdf8407b24f33d508d288e9..a1dfd049a5b6cc3bf40804ad702f3def5b9895b4 100644 (file)
@@ -97,6 +97,12 @@ done
 ENABLED_MODULES="$ENABLED_MODULES ${default_db_mod}.o"
 ])
 
+AC_ARG_ENABLE([glib_mainloop],
+AS_HELP_STRING([--enable-glib-mainloop], [Use Glib mainloop]),
+        [enable_glib_mainloop=$enableval], [enable_glib_mainloop=no])
+
+AM_CONDITIONAL(GLIB_MAINLOOP, [test "x$enable_glib_mainloop" = xyes])
+
 AC_SUBST([ENABLED_MODULES])
 
 PKG_CHECK_MODULES(LIBSYSTEMD,
@@ -106,6 +112,14 @@ PKG_CHECK_MODULES(LIBSYSTEMD,
 AS_IF([test "x$have_libsystemd" = "xno"],
       AC_MSG_ERROR([libsystemd version 221 or newer not found]))
 
+AS_IF([test "x$enable_glib_mainloop" = xyes],
+      [PKG_CHECK_MODULES(GLIB,
+       [glib-2.0],
+       have_glib=yes,
+       have_glib=no)
+      AS_IF([test "x$have_glib" = "xno"],
+      AC_MSG_ERROR([glib not found]))])
+
 PKG_CHECK_MODULES(AUDIT,
         [audit],
         have_audit=yes,
@@ -152,6 +166,7 @@ AC_MSG_RESULT([
         ldflags:                ${LDFLAGS}
 
         libsystemd:             ${have_libsystemd}
+        glib                    ${have_glib}
 
         modules:                ${ENABLED_MODULES/ /}
 ])
index bed34c963287d402685dfbe0a21b769e1d2a8243..7e5b2eea26d011fcb3b9e35697455d7304c47b5c 100644 (file)
@@ -6,10 +6,16 @@ Source0:    %{name}-%{version}.tar.xz
 Source1001: %{name}.manifest
 Summary:    Fault detection daemon
 Group:      System/Monitoring
+
+%define with_faultd_glib_support 0
+
 BuildRequires: pkgconfig(libsystemd)
 BuildRequires: pkgconfig(json-c)
 BuildRequires: pkgconfig(cmocka)
 BuildRequires: pkgconfig(libejdb)
+%if %{with_faultd_glib_support}
+BuildRequires: pkgconfig(glib-2.0)
+%endif
 
 %description
 faultd monitors system services, detects their abnormal execution and
@@ -38,6 +44,9 @@ cp %{SOURCE1001} .
 %autogen
 %configure \
        --enable-test-services \
+%if %{with_faultd_glib_support}
+       --enable-glib-mainloop \
+%endif
        --enable-unit-tests \
        --enable-forced-reboot
 
diff --git a/src/core/faultd-glib.c b/src/core/faultd-glib.c
new file mode 100644 (file)
index 0000000..5de0b01
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * This file is part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <glib.h>
+#include <systemd/sd-event.h>
+#include <errno.h>
+
+#include "common.h"
+#include "faultd-glib.h"
+
+struct faultd_event_source {
+       GSource gsource; /* gsource should be the first field of this structure */
+       sd_event *event;
+};
+
+#define to_faultd_event_source(source) \
+       container_of(source, struct faultd_event_source, gsource)
+
+static gboolean prepare(GSource *source, gint *timeout)
+{
+       struct faultd_event_source *s = to_faultd_event_source(source);
+
+       return sd_event_prepare(s->event);
+}
+
+static gboolean check(GSource *source)
+{
+       struct faultd_event_source *s = to_faultd_event_source(source);
+
+       return sd_event_wait(s->event, 0) > 0;
+}
+
+static gboolean dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
+{
+       struct faultd_event_source *s = to_faultd_event_source(source);
+
+       return sd_event_dispatch(s->event);
+}
+
+static void finalize(GSource *source)
+{
+       struct faultd_event_source *s = to_faultd_event_source(source);
+
+       sd_event_unref(s->event);
+}
+
+static void faultd_on_exit(sd_event_source *s, void *userdata)
+{
+       GMainLoop *gloop = userdata;
+
+       g_main_loop_quit(gloop);
+}
+
+static GSourceFuncs source_funcs = {
+       .prepare = prepare,
+       .check = check,
+       .dispatch = dispatch,
+       .finalize = finalize,
+};
+
+int faultd_g_main_loop_wrapper(sd_event *loop)
+{
+       GMainLoop *gloop;
+       GSource *source;
+       GPollFD pollfd;
+       struct faultd_event_source *s;
+       int ret;
+
+       gloop = g_main_loop_new(NULL, FALSE);
+       if (!gloop)
+               return -ENOMEM;
+
+       source = g_source_new(&source_funcs, sizeof(struct faultd_event_source));
+       if (!source) {
+               ret = -ENOMEM;
+               goto gloop_unref;
+       }
+
+       s = to_faultd_event_source(source);
+       s->event = sd_event_ref(loop);
+       sd_event_add_exit(loop, NULL, faultd_on_exit, gloop);
+
+       pollfd.fd = sd_event_get_fd(loop);
+       pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+       g_source_add_poll(source, &pollfd);
+
+       g_source_attach(source, NULL);
+
+       g_main_loop_run(gloop);
+       ret = 0;
+
+       g_source_unref(source);
+
+gloop_unref:
+       g_main_loop_unref(gloop);
+
+       return ret;
+}
diff --git a/src/core/faultd-glib.h b/src/core/faultd-glib.h
new file mode 100644 (file)
index 0000000..a30d0b0
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * This file is part of faultd.
+ *
+ * Copyright © 2017 Samsung Electronics
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <systemd/sd-event.h>
+
+/**
+ * Run sd_event loop as a part of glib mainloop.
+ * This allows to use glib event sources in modules.
+ */
+int faultd_g_main_loop_wrapper(sd_event *loop);
index 2156471c136ef7c1326146591d6848f8edff08b4..ae4828f5e7da2571e3be93dde0d550bdae577c21 100644 (file)
@@ -32,6 +32,7 @@
 #include "systemd_dbus.h"
 #include "faultd-config.h"
 #include "common.h"
+#include "faultd-glib.h"
 
 static int terminate = 0;
 static struct faultd_config config;
@@ -214,7 +215,14 @@ int main(int ac, char *av[])
 
        printf("Hello world!\n");
 
-       sd_event_loop(loop);
+#ifdef FAULTD_GLIB_MAINLOOP
+       rc = faultd_g_main_loop_wrapper(loop);
+#else
+       rc = sd_event_loop(loop);
+#endif /* FAULTD_GLIB_MAINLOOP */
+
+       if (rc < 0)
+               log_error_errno(rc, "Failed to run main loop: %m");
 
        faultd_modules_cleanup();
        faultd_config_cleanup(&config);