static void *server(void *p) { struct context *c = p; sd_bus *bus = NULL; sd_id128_t id; int r; c->quit = false; assert_se(sd_id128_randomize(&id) >= 0); assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); assert_se(sd_bus_set_server(bus, 1, id) >= 0); assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0); assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0); assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0); assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0); assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value/a", enumerator2_callback, NULL) >= 0); assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0); assert_se(sd_bus_add_object_manager(bus, NULL, "/value/a") >= 0); assert_se(sd_bus_start(bus) >= 0); log_error("Entering event loop on server"); while (!c->quit) { log_error("Loop!"); r = sd_bus_process(bus, NULL); if (r < 0) { log_error_errno(r, "Failed to process requests: %m"); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error_errno(r, "Failed to wait: %m"); goto fail; } continue; } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return INT_TO_PTR(r); }
int main(int argc, char *argv[]) { _cleanup_(sd_bus_unrefp) sd_bus *a = NULL, *b = NULL; sd_id128_t server_id; bool is_unix; int r, in_fd, out_fd; log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); log_open(); r = parse_argv(argc, argv); if (r <= 0) goto finish; r = sd_listen_fds(0); if (r == 0) { in_fd = STDIN_FILENO; out_fd = STDOUT_FILENO; } else if (r == 1) { in_fd = SD_LISTEN_FDS_START; out_fd = SD_LISTEN_FDS_START; } else { log_error("Illegal number of file descriptors passed\n"); goto finish; } is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; r = sd_bus_new(&a); if (r < 0) { log_error_errno(r, "Failed to allocate bus: %m"); goto finish; } r = sd_bus_set_address(a, arg_bus_path); if (r < 0) { log_error_errno(r, "Failed to set address to connect to: %m"); goto finish; } r = sd_bus_negotiate_fds(a, is_unix); if (r < 0) { log_error_errno(r, "Failed to set FD negotiation: %m"); goto finish; } r = sd_bus_start(a); if (r < 0) { log_error_errno(r, "Failed to start bus client: %m"); goto finish; } r = sd_bus_get_bus_id(a, &server_id); if (r < 0) { log_error_errno(r, "Failed to get server ID: %m"); goto finish; } r = sd_bus_new(&b); if (r < 0) { log_error_errno(r, "Failed to allocate bus: %m"); goto finish; } r = sd_bus_set_fd(b, in_fd, out_fd); if (r < 0) { log_error_errno(r, "Failed to set fds: %m"); goto finish; } r = sd_bus_set_server(b, 1, server_id); if (r < 0) { log_error_errno(r, "Failed to set server mode: %m"); goto finish; } r = sd_bus_negotiate_fds(b, is_unix); if (r < 0) { log_error_errno(r, "Failed to set FD negotiation: %m"); goto finish; } r = sd_bus_set_anonymous(b, true); if (r < 0) { log_error_errno(r, "Failed to set anonymous authentication: %m"); goto finish; } r = sd_bus_start(b); if (r < 0) { log_error_errno(r, "Failed to start bus client: %m"); goto finish; } for (;;) { _cleanup_(sd_bus_message_unrefp)sd_bus_message *m = NULL; int events_a, events_b, fd; uint64_t timeout_a, timeout_b, t; struct timespec _ts, *ts; r = sd_bus_process(a, &m); if (r < 0) { log_error_errno(r, "Failed to process bus a: %m"); goto finish; } if (m) { r = sd_bus_send(b, m, NULL); if (r < 0) { log_error_errno(r, "Failed to send message: %m"); goto finish; } } if (r > 0) continue; r = sd_bus_process(b, &m); if (r < 0) { /* treat 'connection reset by peer' as clean exit condition */ if (r == -ECONNRESET) r = 0; goto finish; } if (m) { r = sd_bus_send(a, m, NULL); if (r < 0) { log_error_errno(r, "Failed to send message: %m"); goto finish; } } if (r > 0) continue; fd = sd_bus_get_fd(a); if (fd < 0) { log_error_errno(r, "Failed to get fd: %m"); goto finish; } events_a = sd_bus_get_events(a); if (events_a < 0) { log_error_errno(r, "Failed to get events mask: %m"); goto finish; } r = sd_bus_get_timeout(a, &timeout_a); if (r < 0) { log_error_errno(r, "Failed to get timeout: %m"); goto finish; } events_b = sd_bus_get_events(b); if (events_b < 0) { log_error_errno(r, "Failed to get events mask: %m"); goto finish; } r = sd_bus_get_timeout(b, &timeout_b); if (r < 0) { log_error_errno(r, "Failed to get timeout: %m"); goto finish; } t = timeout_a; if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a)) t = timeout_b; if (t == (uint64_t) -1) ts = NULL; else { usec_t nw; nw = now(CLOCK_MONOTONIC); if (t > nw) t -= nw; else t = 0; ts = timespec_store(&_ts, t); } { struct pollfd p[3] = { {.fd = fd, .events = events_a, }, {.fd = STDIN_FILENO, .events = events_b & POLLIN, }, {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};
int main(int argc, char *argv[]) { enum { MODE_BISECT, MODE_CHART, } mode = MODE_BISECT; Type type = TYPE_KDBUS; int i, pair[2] = { -1, -1 }; _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *server_name = NULL; _cleanup_close_ int bus_ref = -1; const char *unique; cpu_set_t cpuset; size_t result; sd_bus *b; pid_t pid; int r; for (i = 1; i < argc; i++) { if (streq(argv[i], "chart")) { mode = MODE_CHART; continue; } else if (streq(argv[i], "legacy")) { type = TYPE_LEGACY; continue; } else if (streq(argv[i], "direct")) { type = TYPE_DIRECT; continue; } assert_se(parse_sec(argv[i], &arg_loop_usec) >= 0); } assert_se(!MODE_BISECT || TYPE_KDBUS); assert_se(arg_loop_usec > 0); if (type == TYPE_KDBUS) { assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid()) >= 0); bus_ref = bus_kernel_create_bus(name, false, &bus_name); if (bus_ref == -ENOENT) exit(EXIT_TEST_SKIP); assert_se(bus_ref >= 0); address = strappend("kernel:path=", bus_name); assert_se(address); } else if (type == TYPE_LEGACY) { const char *e; e = secure_getenv("DBUS_SESSION_BUS_ADDRESS"); assert_se(e); address = strdup(e); assert_se(address); } r = sd_bus_new(&b); assert_se(r >= 0); if (type == TYPE_DIRECT) { assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) >= 0); r = sd_bus_set_fd(b, pair[0], pair[0]); assert_se(r >= 0); r = sd_bus_set_server(b, true, SD_ID128_NULL); assert_se(r >= 0); } else { r = sd_bus_set_address(b, address); assert_se(r >= 0); r = sd_bus_set_bus_client(b, true); assert_se(r >= 0); } r = sd_bus_start(b); assert_se(r >= 0); if (type != TYPE_DIRECT) { r = sd_bus_get_unique_name(b, &unique); assert_se(r >= 0); server_name = strdup(unique); assert_se(server_name); } sync(); setpriority(PRIO_PROCESS, 0, -19); pid = fork(); assert_se(pid >= 0); if (pid == 0) { CPU_ZERO(&cpuset); CPU_SET(0, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); safe_close(bus_ref); sd_bus_unref(b); switch (mode) { case MODE_BISECT: client_bisect(address, server_name); break; case MODE_CHART: client_chart(type, address, server_name, pair[1]); break; } _exit(0); } CPU_ZERO(&cpuset); CPU_SET(1, &cpuset); pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); server(b, &result); if (mode == MODE_BISECT) printf("Copying/memfd are equally fast at %zu bytes\n", result); assert_se(waitpid(pid, NULL, 0) == pid); safe_close(pair[1]); sd_bus_unref(b); return 0; }
static void *server(void *p) { struct context *c = p; sd_bus *bus = NULL; sd_id128_t id; bool quit = false; int r; assert_se(sd_id128_randomize(&id) >= 0); assert_se(sd_bus_new(&bus) >= 0); assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0); assert_se(sd_bus_set_server(bus, 1, id) >= 0); assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0); assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0); assert_se(sd_bus_start(bus) >= 0); while (!quit) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL; r = sd_bus_process(bus, &m); if (r < 0) { log_error("Failed to process requests: %s", strerror(-r)); goto fail; } if (r == 0) { r = sd_bus_wait(bus, (uint64_t) -1); if (r < 0) { log_error("Failed to wait: %s", strerror(-r)); goto fail; } continue; } if (!m) continue; log_info("Got message! member=%s", strna(sd_bus_message_get_member(m))); if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) { assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds)); r = sd_bus_message_new_method_return(m, &reply); if (r < 0) { log_error("Failed to allocate return: %s", strerror(-r)); goto fail; } quit = true; } else if (sd_bus_message_is_method_call(m, NULL, NULL)) { r = sd_bus_message_new_method_error( m, &reply, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method.")); if (r < 0) { log_error("Failed to allocate return: %s", strerror(-r)); goto fail; } } if (reply) { r = sd_bus_send(bus, reply, NULL); if (r < 0) { log_error("Failed to send reply: %s", strerror(-r)); goto fail; } } } r = 0; fail: if (bus) { sd_bus_flush(bus); sd_bus_unref(bus); } return INT_TO_PTR(r); }
int main(int argc, char *argv[]) { _cleanup_bus_unref_ sd_bus *a = NULL, *b = NULL; sd_id128_t server_id; bool is_unix; int r; if (argc > 1) { log_error("This program takes no argument."); return EXIT_FAILURE; } log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); log_open(); is_unix = sd_is_socket(STDIN_FILENO, AF_UNIX, 0, 0) > 0 && sd_is_socket(STDOUT_FILENO, AF_UNIX, 0, 0) > 0; r = sd_bus_new(&a); if (r < 0) { log_error("Failed to allocate bus: %s", strerror(-r)); goto finish; } r = sd_bus_set_address(a, "unix:path=/run/dbus/system_bus_socket"); if (r < 0) { log_error("Failed to set address to connect to: %s", strerror(-r)); goto finish; } r = sd_bus_set_negotiate_fds(a, is_unix); if (r < 0) { log_error("Failed to set FD negotiation: %s", strerror(-r)); goto finish; } r = sd_bus_start(a); if (r < 0) { log_error("Failed to start bus client: %s", strerror(-r)); goto finish; } r = sd_bus_get_server_id(a, &server_id); if (r < 0) { log_error("Failed to get server ID: %s", strerror(-r)); goto finish; } r = sd_bus_new(&b); if (r < 0) { log_error("Failed to allocate bus: %s", strerror(-r)); goto finish; } r = sd_bus_set_fd(b, STDIN_FILENO, STDOUT_FILENO); if (r < 0) { log_error("Failed to set fds: %s", strerror(-r)); goto finish; } r = sd_bus_set_server(b, 1, server_id); if (r < 0) { log_error("Failed to set server mode: %s", strerror(-r)); goto finish; } r = sd_bus_set_negotiate_fds(b, is_unix); if (r < 0) { log_error("Failed to set FD negotiation: %s", strerror(-r)); goto finish; } r = sd_bus_set_anonymous(b, true); if (r < 0) { log_error("Failed to set anonymous authentication: %s", strerror(-r)); goto finish; } r = sd_bus_start(b); if (r < 0) { log_error("Failed to start bus client: %s", strerror(-r)); goto finish; } for (;;) { _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int events_a, events_b, fd; uint64_t timeout_a, timeout_b, t; struct timespec _ts, *ts; r = sd_bus_process(a, &m); if (r < 0) { log_error("Failed to process bus: %s", strerror(-r)); goto finish; } if (m) { r = sd_bus_send(b, m, NULL); if (r < 0) { log_error("Failed to send message: %s", strerror(-r)); goto finish; } } if (r > 0) continue; r = sd_bus_process(b, &m); if (r < 0) { log_error("Failed to process bus: %s", strerror(-r)); goto finish; } if (m) { r = sd_bus_send(a, m, NULL); if (r < 0) { log_error("Failed to send message: %s", strerror(-r)); goto finish; } } if (r > 0) continue; fd = sd_bus_get_fd(a); if (fd < 0) { log_error("Failed to get fd: %s", strerror(-r)); goto finish; } events_a = sd_bus_get_events(a); if (events_a < 0) { log_error("Failed to get events mask: %s", strerror(-r)); goto finish; } r = sd_bus_get_timeout(a, &timeout_a); if (r < 0) { log_error("Failed to get timeout: %s", strerror(-r)); goto finish; } events_b = sd_bus_get_events(b); if (events_b < 0) { log_error("Failed to get events mask: %s", strerror(-r)); goto finish; } r = sd_bus_get_timeout(b, &timeout_b); if (r < 0) { log_error("Failed to get timeout: %s", strerror(-r)); goto finish; } t = timeout_a; if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a)) t = timeout_b; if (t == (uint64_t) -1) ts = NULL; else { usec_t nw; nw = now(CLOCK_MONOTONIC); if (t > nw) t -= nw; else t = 0; ts = timespec_store(&_ts, t); } { struct pollfd p[3] = { {.fd = fd, .events = events_a, }, {.fd = STDIN_FILENO, .events = events_b & POLLIN, }, {.fd = STDOUT_FILENO, .events = events_b & POLLOUT, }};