579 lines
22 KiB
Diff
579 lines
22 KiB
Diff
From 2c51932c86b5dfc3a81b9203875ca45216f45c3a Mon Sep 17 00:00:00 2001
|
|
From: rpm-build <rpm-build>
|
|
Date: Fri, 10 Mar 2023 11:46:16 +0800
|
|
Subject: [PATCH 2/2] add unit test for dbus-broker
|
|
|
|
---
|
|
test/dbus/meson.build | 6 ++
|
|
test/dbus/test-reexecute.c | 121 +++++++++++++++++++++++++++++++
|
|
test/dbus/test-serialize.c | 144 +++++++++++++++++++++++++++++++++++++
|
|
test/dbus/util-broker.c | 138 ++++++++++++++++++++++++++++++-----
|
|
test/dbus/util-broker.h | 12 +++-
|
|
5 files changed, 401 insertions(+), 20 deletions(-)
|
|
create mode 100755 test/dbus/test-reexecute.c
|
|
create mode 100755 test/dbus/test-serialize.c
|
|
|
|
diff --git a/test/dbus/meson.build b/test/dbus/meson.build
|
|
index c111283..c2d1d79 100644
|
|
--- a/test/dbus/meson.build
|
|
+++ b/test/dbus/meson.build
|
|
@@ -67,6 +67,12 @@ test('Client Lifetime', test_lifetime)
|
|
test_matches = executable('test-matches', ['test-matches.c'], dependencies: [ dep_test ])
|
|
test('Signals and Matches', test_matches)
|
|
|
|
+test_serialize = executable('test-serialize', ['test-serialize.c'], dependencies: [ dep_test ])
|
|
+test('Serialize and Deserialize', test_serialize)
|
|
+
|
|
+test_reexecute = executable('test-reexecute', ['test-reexecute.c'], dependencies: [ dep_test ])
|
|
+test('Reexecute', test_reexecute)
|
|
+
|
|
if use_reference_test
|
|
dbus_bin = dep_dbus.get_pkgconfig_variable('bindir') + '/dbus-daemon'
|
|
|
|
diff --git a/test/dbus/test-reexecute.c b/test/dbus/test-reexecute.c
|
|
new file mode 100755
|
|
index 0000000..43025e7
|
|
--- /dev/null
|
|
+++ b/test/dbus/test-reexecute.c
|
|
@@ -0,0 +1,121 @@
|
|
+/*
|
|
+ * Reexecute Tests
|
|
+ */
|
|
+
|
|
+#undef NDEBUG
|
|
+#include <c-stdaux.h>
|
|
+#include <systemd/sd-bus.h>
|
|
+#include <unistd.h>
|
|
+#include "util-broker.h"
|
|
+#include "util/string.h"
|
|
+#include "syslog.h"
|
|
+
|
|
+#define PATH_LENGTH_MAX 4096
|
|
+#define TEST_ARG_MAX 12
|
|
+
|
|
+static void test_send_reexecute() {
|
|
+ Broker *broker = NULL;
|
|
+ int r, sync_pairs[2], sync_value;
|
|
+
|
|
+ r = socketpair(AF_UNIX, SOCK_STREAM, 0, sync_pairs);
|
|
+ assert(r >= 0);
|
|
+
|
|
+ util_broker_new(&broker);
|
|
+ broker->test_reexec = true;
|
|
+ util_broker_spawn(broker);
|
|
+ pid_t pid = fork();
|
|
+ if (pid != 0) {
|
|
+ close(sync_pairs[1]);
|
|
+ /* Wait the child process exits. */
|
|
+ read(sync_pairs[0], &sync_value, sizeof(sync_value));
|
|
+ util_broker_terminate(broker);
|
|
+ util_broker_free(broker);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ close(sync_pairs[0]);
|
|
+ _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *server = NULL, *cmd_bus = NULL;
|
|
+ _c_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
|
+ const char *unique_name = NULL, *owner = NULL, *reply_str = NULL;
|
|
+
|
|
+ /* RequestName before reexecuting. */
|
|
+ {
|
|
+ util_broker_connect(broker, &server);
|
|
+ r = sd_bus_get_unique_name(server, &unique_name);
|
|
+ c_assert(r >= 0);
|
|
+ r = sd_bus_call_method(server, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
|
|
+ "RequestName", NULL, NULL, "su", "com.example.foo", 0);
|
|
+ c_assert(r >= 0);
|
|
+ }
|
|
+
|
|
+ /* Make broker reexecute. */
|
|
+ {
|
|
+ util_broker_connect(broker, &cmd_bus);
|
|
+ r = sd_bus_call_method(cmd_bus, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
|
|
+ "Reexecute", NULL, &reply, "");
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_message_read(reply, "s", &reply_str);
|
|
+ c_assert(r >= 0);
|
|
+ c_assert(!strcmp(reply_str, "OK"));
|
|
+
|
|
+ sd_bus_flush_close_unref(cmd_bus);
|
|
+ }
|
|
+
|
|
+ /* Wait to make sure dbus-broker has exited. */
|
|
+ sleep(1);
|
|
+
|
|
+ /* GetNameOwner after reexecuting. */
|
|
+ {
|
|
+ r = sd_bus_call_method(server, "org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus",
|
|
+ "GetNameOwner", NULL, &reply, "s", "com.example.foo");
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_message_read(reply, "s", &owner);
|
|
+ c_assert(r >= 0);
|
|
+ c_assert(!strcmp(owner, unique_name));
|
|
+ syslog(LOG_INFO, "Got the right owner!");
|
|
+ }
|
|
+
|
|
+ /* Clean.
|
|
+ * We can't call util_broker_terminate, because the forked process
|
|
+ * is single thread, util_broker_thread doesn't exist and can't do
|
|
+ * this for us.
|
|
+ */
|
|
+
|
|
+ broker->pipe_fds[0] = c_close(broker->pipe_fds[0]);
|
|
+ broker->pipe_fds[1] = c_close(broker->pipe_fds[1]);
|
|
+ broker->listener_fd = c_close(broker->listener_fd);
|
|
+ util_broker_free(broker);
|
|
+ write(sync_pairs[1], &sync_value, sizeof(sync_value));
|
|
+}
|
|
+
|
|
+static void test_generate_args_string() {
|
|
+ char *args[TEST_ARG_MAX];
|
|
+ for (int i = 0; i < TEST_ARG_MAX; i++) {
|
|
+ args[i] = NULL;
|
|
+ }
|
|
+ int i = 0;
|
|
+ generate_args_string(false, args, TEST_ARG_MAX, &i, "--log", "1");
|
|
+ c_assert(i == 0 && args[i] == NULL);
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--controller", "2");
|
|
+ c_assert(i == 2 && !strcmp(args[0], "--controller") && !strcmp(args[1], "2"));
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--machine-id", "3");
|
|
+ c_assert(i == 4 && !strcmp(args[2], "--machine-id") && !strcmp(args[3], "3"));
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--max-bytes", "123456");
|
|
+ c_assert(i == 6 && !strcmp(args[4], "--max-bytes") && !strcmp(args[5], "123456"));
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--max-fds", "12");
|
|
+ c_assert(i == 8 && !strcmp(args[6], "--max-fds") && !strcmp(args[7], "12"));
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--max-matches", "12345abcde");
|
|
+ c_assert(i == 10 && !strcmp(args[8], "--max-matches") && !strcmp(args[9], "12345abcde"));
|
|
+ generate_args_string(true, args, TEST_ARG_MAX, &i, "--reexec", "13");
|
|
+ c_assert(i == 10 && args[10] == NULL && args[11] == NULL);
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv) {
|
|
+ test_generate_args_string();
|
|
+ /* Reexecute can only be run under privileged user */
|
|
+ if (getuid() == 0)
|
|
+ test_send_reexecute();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/test/dbus/test-serialize.c b/test/dbus/test-serialize.c
|
|
new file mode 100755
|
|
index 0000000..e287647
|
|
--- /dev/null
|
|
+++ b/test/dbus/test-serialize.c
|
|
@@ -0,0 +1,144 @@
|
|
+/*
|
|
+ * Serialize and Deserialize Tests
|
|
+ */
|
|
+
|
|
+#undef NDEBUG
|
|
+#include <c-stdaux.h>
|
|
+#include <stdlib.h>
|
|
+#include "util/serialize.h"
|
|
+#include "util/string.h"
|
|
+
|
|
+static void test_basic() {
|
|
+ FILE *f = NULL;
|
|
+ _c_cleanup_(c_freep) char *buf = malloc(LINE_LENGTH_MAX);
|
|
+ int mem_fd;
|
|
+
|
|
+ mem_fd = state_file_init(&f);
|
|
+ c_assert(mem_fd > 0);
|
|
+
|
|
+ c_assert(!serialize_basic(f, "test_u", "%u", 1234));
|
|
+ c_assert(!serialize_basic(f, "test_d", "%d", -1234));
|
|
+ c_assert(!serialize_basic(f, "test_s", "%s", "test"));
|
|
+ c_assert(!serialize_basic(f, "test_uds", "%u;%d;%s", 1234, -1234, "test"));
|
|
+
|
|
+ fseeko(f, 0, SEEK_SET);
|
|
+
|
|
+ if (fgets(buf, LINE_LENGTH_MAX, f) != NULL)
|
|
+ c_assert(!strcmp(buf, "test_u=1234\n"));
|
|
+ if (fgets(buf, LINE_LENGTH_MAX, f) != NULL)
|
|
+ c_assert(!strcmp(buf, "test_d=-1234\n"));
|
|
+ if (fgets(buf, LINE_LENGTH_MAX, f) != NULL)
|
|
+ c_assert(!strcmp(buf, "test_s=test\n"));
|
|
+ if (fgets(buf, LINE_LENGTH_MAX, f) != NULL)
|
|
+ c_assert(!strcmp(buf, "test_uds=1234;-1234;test\n"));
|
|
+
|
|
+ c_assert(!fgets(buf, LINE_LENGTH_MAX, f));
|
|
+}
|
|
+
|
|
+static void test_extract_world_inlist() {
|
|
+ char *list1 = ";;a;b;;c;;;";
|
|
+ char *list2 = "a;;bb;ccc;;;";
|
|
+ char *res1[] = {"a", "b", "c"};
|
|
+ char *res2[] = {"a", "bb", "ccc"};
|
|
+ char *res = malloc(10);
|
|
+
|
|
+ int i = 0;
|
|
+ while (true) {
|
|
+ list1 = extract_word_inlist(list1, &res, 1);
|
|
+ if (!list1)
|
|
+ break;
|
|
+ c_assert(!strcmp(res, res1[i++]));
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ while (true) {
|
|
+ list2 = extract_word_inlist(list2, &res, 3);
|
|
+ if (!list2)
|
|
+ break;
|
|
+ c_assert(!strcmp(res, res2[i++]));
|
|
+ }
|
|
+ free(res);
|
|
+}
|
|
+
|
|
+static void test_extract_list_element() {
|
|
+ char *list1 = "[{}]";
|
|
+ char *list2 = "[{a}{b}{c}]";
|
|
+ char *list3 = "[{a}{{{b}}{}}{c}]";
|
|
+ char *res2_3[] = {"a", "b", "c"};
|
|
+ char *res = NULL;
|
|
+
|
|
+ int i = 0;
|
|
+ while (true) {
|
|
+ list1 = extract_list_element(list1, &res);
|
|
+ if (!list1)
|
|
+ break;
|
|
+ c_assert(!res);
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+
|
|
+ if (res) {
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ while (true) {
|
|
+ list2 = extract_list_element(list2, &res);
|
|
+ if (!list2)
|
|
+ break;
|
|
+ c_assert(!strcmp(res, res2_3[i++]));
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+ if (res) {
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+
|
|
+ i = 0;
|
|
+ while (true) {
|
|
+ list3 = extract_list_element(list3, &res);
|
|
+ if (!list3)
|
|
+ break;
|
|
+ c_assert(!strcmp(res, res2_3[i++]));
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+ if (res) {
|
|
+ free(res);
|
|
+ res = NULL;
|
|
+ }
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void test_serialize_validate_rule() {
|
|
+ const char *rule_str_ok[3] = {"[{123}{234}{.a-*(*&^@#*^)}]", "[{123}]", "[]"};
|
|
+ const char *rule_str_bad[8] = {"oaeu", "[{{]", "[{123}}", "{123}{345}", "[{{11111}}]", "[aoeuaou]", "[{{}}]", "[aa{b}aa{b}]"};
|
|
+
|
|
+ for (int i = 0; i < 3; i++)
|
|
+ c_assert(serialize_validate_rule(rule_str_ok[i]) == true);
|
|
+
|
|
+ for (int i = 0; i < 8; i++)
|
|
+ c_assert(serialize_validate_rule(rule_str_bad[i]) == false);
|
|
+}
|
|
+
|
|
+static void test_serialize_validate_sasl() {
|
|
+ const char *sasl_str_ok[2] = {"[{0}{0}{1}]", "[{1}{1}{3}"};
|
|
+ const char *sasl_str_bad[6] = {"[{-1}{}{}]", "foo", "[{-1}{0}{-1}]", "[{5}{1}{0}]", "[123", "123323"};
|
|
+
|
|
+ for (int i = 0; i < 2; i++)
|
|
+ c_assert(serialize_validate_sasl(sasl_str_ok[i]) == true);
|
|
+
|
|
+ for (int i = 0; i < 6; i++)
|
|
+ c_assert(serialize_validate_sasl(sasl_str_bad[i]) == false);
|
|
+}
|
|
+
|
|
+int main(int argc, char **argv) {
|
|
+ test_basic();
|
|
+ test_extract_world_inlist();
|
|
+ test_extract_list_element();
|
|
+ test_serialize_validate_rule();
|
|
+ test_serialize_validate_sasl();
|
|
+ return 0;
|
|
+}
|
|
diff --git a/test/dbus/util-broker.c b/test/dbus/util-broker.c
|
|
index 0bdcefc..5d33b52 100644
|
|
--- a/test/dbus/util-broker.c
|
|
+++ b/test/dbus/util-broker.c
|
|
@@ -15,6 +15,7 @@
|
|
#include <systemd/sd-bus.h>
|
|
#include <systemd/sd-event.h>
|
|
#include "dbus/protocol.h"
|
|
+#include "util/proc.h"
|
|
#include "util/syscall.h"
|
|
#include "util-broker.h"
|
|
|
|
@@ -35,7 +36,8 @@ void util_event_new(sd_event **eventp) {
|
|
}
|
|
|
|
static int util_event_sigchld(sd_event_source *source, const siginfo_t *si, void *userdata) {
|
|
- int status;
|
|
+ int status, r;
|
|
+ Broker* broker = userdata;
|
|
|
|
if (si->si_code == CLD_EXITED)
|
|
status = si->si_status;
|
|
@@ -47,6 +49,70 @@ static int util_event_sigchld(sd_event_source *source, const siginfo_t *si, void
|
|
return sd_event_exit(sd_event_source_get_event(source), status);
|
|
}
|
|
|
|
+static int util_event_sigchld_reexec(sd_event_source *source, const struct signalfd_siginfo *ssi, void *userdata) {
|
|
+ int status, r;
|
|
+ Broker* broker = userdata;
|
|
+
|
|
+ if (ssi->ssi_pid == broker->child_pid)
|
|
+ return sd_event_source_set_enabled(broker->defer_event_source, SD_EVENT_ONESHOT);
|
|
+}
|
|
+
|
|
+static int util_event_defer(sd_event_source *source, void *userdata) {
|
|
+ Broker *broker = userdata;
|
|
+ sd_bus *bus = broker->bus;
|
|
+ /* new_bus shares the dbus fd (pair[0] or lc_fd) with broker->bus.
|
|
+ * Both of them use this fd to communicate with broker, which use
|
|
+ * pair[1]. So we can't close new_bus here, or we will fail when
|
|
+ * closing broker->bus.
|
|
+ * And, before sending messages to the broker by new_bus, we should
|
|
+ * detach broker->bus. If not, the reply message will be processed
|
|
+ * by broker->bus, but broker->bus have no idea why this message even
|
|
+ * exist, because it doesn't send any message.
|
|
+ */
|
|
+ sd_bus_detach_event(bus);
|
|
+ sd_bus *new_bus;
|
|
+ _c_cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
|
|
+ int r = 0;
|
|
+
|
|
+ create_broker_listener(broker);
|
|
+
|
|
+ r = sd_bus_new(&new_bus);
|
|
+ assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_set_fd(new_bus, broker->lc_fd, broker->lc_fd);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_start(new_bus);
|
|
+ assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_message_new_method_call(new_bus,
|
|
+ &message,
|
|
+ NULL,
|
|
+ "/org/bus1/DBus/Broker",
|
|
+ "org.bus1.DBus.Broker",
|
|
+ "AddListener");
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_message_append(message,
|
|
+ "oh",
|
|
+ "/org/bus1/DBus/Listener/0",
|
|
+ broker->listener_fd);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = util_append_policy(message);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_bus_call(new_bus, message, -1, NULL, NULL);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ /* close the new listener_fd just like what we have done in util_broker_thread. */
|
|
+ broker->listener_fd = c_close(broker->listener_fd);
|
|
+
|
|
+ /* We still need broker->bus to deal some message, reattach it. */
|
|
+ sd_bus_attach_event(bus, sd_event_source_get_event(source), SD_EVENT_PRIORITY_NORMAL);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
#define POLICY_T_BATCH \
|
|
"bt" \
|
|
"a(btbs)" \
|
|
@@ -59,7 +125,7 @@ static int util_event_sigchld(sd_event_source *source, const siginfo_t *si, void
|
|
"a(ss)" \
|
|
"b"
|
|
|
|
-static int util_append_policy(sd_bus_message *m) {
|
|
+int util_append_policy(sd_bus_message *m) {
|
|
int r;
|
|
|
|
r = sd_bus_message_open_container(m, 'v', "(" POLICY_T ")");
|
|
@@ -165,18 +231,49 @@ static int util_method_reload_config(sd_bus_message *message, void *userdata, sd
|
|
return sd_bus_reply_method_return(message, NULL);
|
|
}
|
|
|
|
+static int util_method_reexecute(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
|
+ /* Careful: Don't return 0, or we will get ECONNRESET in libsystemd. */
|
|
+ /* backtrace:
|
|
+ bus_process_object
|
|
+ ↳ object_find_and_run
|
|
+ ↳ method_callbacks_run
|
|
+ ↳ r = c->vtable->x.method.handler(m, u, &error);
|
|
+ */
|
|
+ return sd_bus_reply_method_return(message, NULL);
|
|
+}
|
|
+
|
|
const sd_bus_vtable util_vtable[] = {
|
|
SD_BUS_VTABLE_START(0),
|
|
|
|
SD_BUS_METHOD("ReloadConfig", NULL, NULL, util_method_reload_config, 0),
|
|
+ SD_BUS_METHOD("Reexecute", NULL, NULL, util_method_reexecute, 0),
|
|
|
|
SD_BUS_VTABLE_END
|
|
};
|
|
|
|
-void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pidp) {
|
|
- _c_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
|
+int create_broker_listener(Broker *broker) {
|
|
+ int r;
|
|
+
|
|
+ broker->listener_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
|
+ c_assert(broker->listener_fd >= 0);
|
|
+
|
|
+ r = bind(broker->listener_fd, (struct sockaddr *)&broker->address, offsetof(struct sockaddr_un, sun_path));
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = getsockname(broker->listener_fd, (struct sockaddr *)&broker->address, &broker->n_address);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = listen(broker->listener_fd, 256);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pidp, int *lc_fd, Broker* broker) {
|
|
+ sd_bus *bus = NULL;
|
|
_c_cleanup_(sd_bus_message_unrefp) sd_bus_message *message = NULL;
|
|
_c_cleanup_(c_freep) char *fdstr = NULL;
|
|
+ sd_event_source *defer_event_source = NULL;
|
|
int r, pair[2];
|
|
pid_t pid;
|
|
|
|
@@ -214,7 +311,13 @@ void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pi
|
|
if (pidp)
|
|
*pidp = pid;
|
|
|
|
- r = sd_event_add_child(event, NULL, pid, WEXITED, util_event_sigchld, NULL);
|
|
+ r = sd_event_add_child(event, NULL, pid, WCONTINUED | WEXITED, util_event_sigchld, broker);
|
|
+ c_assert(r >= 0);
|
|
+
|
|
+ r = sd_event_add_defer(event, &defer_event_source, util_event_defer, broker);
|
|
+ c_assert(r >= 0);
|
|
+ broker->defer_event_source = defer_event_source;
|
|
+ r = sd_event_source_set_enabled(defer_event_source, SD_EVENT_OFF);
|
|
c_assert(r >= 0);
|
|
|
|
r = sd_bus_new(&bus);
|
|
@@ -223,11 +326,12 @@ void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pi
|
|
/* consumes the fd */
|
|
r = sd_bus_set_fd(bus, pair[0], pair[0]);
|
|
c_assert(r >= 0);
|
|
+ *lc_fd = pair[0];
|
|
|
|
r = sd_bus_attach_event(bus, event, SD_EVENT_PRIORITY_NORMAL);
|
|
c_assert(r >= 0);
|
|
|
|
- r = sd_bus_add_object_vtable(bus, NULL, "/org/bus1/DBus/Controller", "org.bus1.DBus.Controller", util_vtable, NULL);
|
|
+ r = sd_bus_add_object_vtable(bus, NULL, "/org/bus1/DBus/Controller", "org.bus1.DBus.Controller", util_vtable, broker);
|
|
c_assert(r >= 0);
|
|
|
|
r = sd_bus_start(bus);
|
|
@@ -381,10 +485,16 @@ static void *util_broker_thread(void *userdata) {
|
|
r = sd_event_add_signal(event, NULL, SIGUSR1, util_event_sigusr1, broker);
|
|
c_assert(r >= 0);
|
|
|
|
+ if (broker->test_reexec) {
|
|
+ r = sd_event_add_signal(event, NULL, SIGCHLD, util_event_sigchld_reexec, broker);
|
|
+ c_assert(r >= 0);
|
|
+ }
|
|
+
|
|
if (broker->listener_fd >= 0) {
|
|
- util_fork_broker(&bus, event, broker->listener_fd, &broker->child_pid);
|
|
+ util_fork_broker(&bus, event, broker->listener_fd, &broker->child_pid, &broker->lc_fd, broker);
|
|
/* dbus-broker reports its controller in GetConnectionUnixProcessID */
|
|
broker->pid = getpid();
|
|
+ broker->bus = bus;
|
|
broker->listener_fd = c_close(broker->listener_fd);
|
|
} else {
|
|
c_assert(broker->listener_fd < 0);
|
|
@@ -478,18 +588,7 @@ void util_broker_spawn(Broker *broker) {
|
|
* run and babysit the broker.
|
|
*/
|
|
|
|
- broker->listener_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
|
|
- c_assert(broker->listener_fd >= 0);
|
|
-
|
|
- r = bind(broker->listener_fd, (struct sockaddr *)&broker->address, offsetof(struct sockaddr_un, sun_path));
|
|
- c_assert(r >= 0);
|
|
-
|
|
- r = getsockname(broker->listener_fd, (struct sockaddr *)&broker->address, &broker->n_address);
|
|
- c_assert(r >= 0);
|
|
-
|
|
- r = listen(broker->listener_fd, 256);
|
|
- c_assert(r >= 0);
|
|
-
|
|
+ create_broker_listener(broker);
|
|
r = pthread_create(&broker->thread, NULL, util_broker_thread, broker);
|
|
c_assert(r >= 0);
|
|
}
|
|
@@ -512,6 +611,7 @@ void util_broker_terminate(Broker *broker) {
|
|
|
|
r = pthread_join(broker->thread, &value);
|
|
c_assert(!r);
|
|
+
|
|
c_assert(!value);
|
|
|
|
c_assert(broker->listener_fd < 0);
|
|
diff --git a/test/dbus/util-broker.h b/test/dbus/util-broker.h
|
|
index a3f5f49..fa6de9d 100644
|
|
--- a/test/dbus/util-broker.h
|
|
+++ b/test/dbus/util-broker.h
|
|
@@ -20,6 +20,10 @@ struct Broker {
|
|
pthread_t thread;
|
|
struct sockaddr_un address;
|
|
socklen_t n_address;
|
|
+ sd_bus *bus;
|
|
+ sd_event_source *defer_event_source;
|
|
+ bool test_reexec;
|
|
+ int lc_fd; /* launcher controller fd */
|
|
int listener_fd;
|
|
int pipe_fds[2];
|
|
pid_t pid;
|
|
@@ -29,6 +33,10 @@ struct Broker {
|
|
#define BROKER_NULL { \
|
|
.address.sun_family = AF_UNIX, \
|
|
.n_address = sizeof(struct sockaddr_un), \
|
|
+ .bus = NULL, \
|
|
+ .defer_event_source = NULL, \
|
|
+ .test_reexec = false, \
|
|
+ .lc_fd = -1, \
|
|
.listener_fd = -1, \
|
|
.pipe_fds[0] = -1, \
|
|
.pipe_fds[1] = -1, \
|
|
@@ -37,7 +45,9 @@ struct Broker {
|
|
/* misc */
|
|
|
|
void util_event_new(sd_event **eventp);
|
|
-void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pidp);
|
|
+int util_append_policy(sd_bus_message *m);
|
|
+int create_broker_listener(Broker *broker);
|
|
+void util_fork_broker(sd_bus **busp, sd_event *event, int listener_fd, pid_t *pidp, int *lc_fd, Broker *broker);
|
|
void util_fork_daemon(sd_event *event, int pipe_fd, pid_t *pidp);
|
|
|
|
/* broker */
|
|
--
|
|
2.30.2
|
|
|