1
0
mirror of https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git synced 2026-10-24 00:48:53 +03:00
Files
libgpiod/dbus/tests/daemon-process.c
Bartosz Golaszewski a5ab76da1e dbus: add the D-Bus daemon, command-line client and tests
Add the D-Bus API definition and its implementation in the form of a GPIO
manager daemon and a companion command-line client as well as some
additional configuration and data files (systemd service, example udev
configuration, etc.) and test suites.

Tested-by: Alexander Sverdlin <alexander.sverdlin@siemens.com>
Link: https://lore.kernel.org/r/20240812-dbus-v5-4-ead288509217@linaro.org
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
2024-08-13 10:45:25 +02:00

130 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0-or-later
// SPDX-FileCopyrightText: 2022-2023 Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
#include <gio/gio.h>
#include <signal.h>
#include "daemon-process.h"
struct _GpiodbusDaemonProcess {
GObject parent_instance;
GSubprocess *proc;
};
G_DEFINE_TYPE(GpiodbusDaemonProcess, gpiodbus_daemon_process, G_TYPE_OBJECT);
static gboolean on_timeout(gpointer data G_GNUC_UNUSED)
{
g_error("timeout reached waiting for the daemon name to appear on the system bus");
return G_SOURCE_REMOVE;
}
static void on_name_appeared(GDBusConnection *con G_GNUC_UNUSED,
const gchar *name G_GNUC_UNUSED,
const gchar *name_owner G_GNUC_UNUSED,
gpointer data)
{
gboolean *name_state = data;
*name_state = TRUE;
}
static void gpiodbus_daemon_process_constructed(GObject *obj)
{
GpiodbusDaemonProcess *self = GPIODBUS_DAEMON_PROCESS_OBJ(obj);
const gchar *path = g_getenv("GPIODBUS_TEST_DAEMON_PATH");
g_autoptr(GDBusConnection) con = NULL;
g_autofree gchar *addr = NULL;
g_autoptr(GError) err = NULL;
gboolean name_state = FALSE;
guint watch_id, timeout_id;
if (!path)
g_error("GPIODBUS_TEST_DAEMON_PATH environment variable must be set");
addr = g_dbus_address_get_for_bus_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
if (!addr)
g_error("failed to get an address for system bus: %s",
err->message);
con = g_dbus_connection_new_for_address_sync(addr,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
NULL, NULL, &err);
if (!con)
g_error("failed to get a dbus connection: %s", err->message);
watch_id = g_bus_watch_name_on_connection(con, "io.gpiod1",
G_BUS_NAME_WATCHER_FLAGS_NONE,
on_name_appeared, NULL,
&name_state, NULL);
self->proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_SILENCE |
G_SUBPROCESS_FLAGS_STDERR_SILENCE,
&err, path, NULL);
if (!self->proc)
g_error("failed to launch the gpio-manager process: %s",
err->message);
timeout_id = g_timeout_add_seconds(5, on_timeout, NULL);
while (!name_state)
g_main_context_iteration(NULL, TRUE);
g_bus_unwatch_name(watch_id);
g_source_remove(timeout_id);
G_OBJECT_CLASS(gpiodbus_daemon_process_parent_class)->constructed(obj);
}
static void gpiodbus_daemon_process_kill(GSubprocess *proc)
{
g_autoptr(GError) err = NULL;
gint status;
g_subprocess_send_signal(proc, SIGTERM);
g_subprocess_wait(proc, NULL, &err);
if (err)
g_error("failed to collect the exit status of gpio-manager: %s",
err->message);
if (!g_subprocess_get_if_exited(proc))
g_error("dbus-manager process did not exit normally");
status = g_subprocess_get_exit_status(proc);
if (status != 0)
g_error("dbus-manager process exited with a non-zero status: %d",
status);
g_object_unref(proc);
}
static void gpiodbus_daemon_process_dispose(GObject *obj)
{
GpiodbusDaemonProcess *self = GPIODBUS_DAEMON_PROCESS_OBJ(obj);
g_clear_pointer(&self->proc, gpiodbus_daemon_process_kill);
G_OBJECT_CLASS(gpiodbus_daemon_process_parent_class)->dispose(obj);
}
static void
gpiodbus_daemon_process_class_init(GpiodbusDaemonProcessClass *proc_class)
{
GObjectClass *class = G_OBJECT_CLASS(proc_class);
class->constructed = gpiodbus_daemon_process_constructed;
class->dispose = gpiodbus_daemon_process_dispose;
}
static void gpiodbus_daemon_process_init(GpiodbusDaemonProcess *self)
{
self->proc = NULL;
}
GpiodbusDaemonProcess *gpiodbus_daemon_process_new(void)
{
return g_object_new(GPIODBUS_DAEMON_PROCESS_TYPE, NULL);
}