From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id AC5352654C; Mon, 03 Nov 2025 08:07:32 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 3789D264F8; Mon, 03 Nov 2025 08:07:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-0.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DMARC_PASS,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE, SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=4.0.1 Received: from mail-yw1-x112b.google.com (mail-yw1-x112b.google.com [IPv6:2607:f8b0:4864:20::112b]) by atuin.qyliss.net (Postfix) with ESMTPS id 0932D26528 for ; Mon, 03 Nov 2025 08:07:29 +0000 (UTC) Received: by mail-yw1-x112b.google.com with SMTP id 00721157ae682-781014f4e12so56979757b3.1 for ; Mon, 03 Nov 2025 00:07:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1762157246; x=1762762046; darn=spectrum-os.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=WVxhgCUBokUz1RFCyaoSflbsPOeSesbTCmkdq+gNpyM=; b=HgNbE2qsJ284OGON/CQyU5R1m0ebf6jbRMENn9xI5G0uv206hj8Q5nr/wxgE9adhwd o2ZKY4+nwPRlortYECSFWzTZIQNiPrY6FZFaOYSguz+QmQAfNfT/I096PiMVs9RSLzVQ QsHdCbuE4JneRKxenGC8FaUA7EOe0QX9c6kXX2obDtl9eD57RgMSU74yuxJ2+6sk0rva EoNy468NjY6gS1FpEJkfWVfOVw6tOXy3P3ROQVCxnXqS8WqQsW8PHT+SxLxiBKMdfQmd Zs9bFnTQ60KTOq7FmwG+2xOO8aXUiG46nGsnE5G4kPTElQAwtVq3JwmBbRfIP/BR54Vg f6nQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1762157246; x=1762762046; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WVxhgCUBokUz1RFCyaoSflbsPOeSesbTCmkdq+gNpyM=; b=wLelI+j/UuLS9BddTzqa0vkz9ogWmzNqfM664HJNocNwqXgKSRhAoq3y6xdH7Z3noo 3sbmOYzBP8grjGil+IHbu5vY/dR71FBp7mdSjGCTHxuwjl2a2ejPlTi9PzuA13GkGswa UH/aK77AkWmABvBcdOnueoSGgydktEbRJ2f6pnJcOLC3PUaZ0YSoPdhNm7WiILJcjhL2 QnmoXGLpx/0eV5N8XQHueZcPb2DH5flg5pw2vv5wc5hm3Ezh3pTDAatbMhLY+6rEkY8i 3li9FNXKokHe07GPD74nGePfuD95mitRMsRPpb9RICXU21oRQpxDQHoig2vDE4gGR+Ir kTaQ== X-Gm-Message-State: AOJu0Yw/l6vVr8oU5yg0eEdOS/JOoyh6HucD5uKv1mxDbE+JlgiSjH6o nqaiS010J9t3R7XEcxvdwDiUJfFdvYNlDDX9eHHX4YkRq/vl/umqE6uV9J8TQg== X-Gm-Gg: ASbGncuaWZG5hLi3zdbdgVljZC3Qn5Lzk3j+2mnu5TKMj60haN6t3ea+1CnSeV6hxkC 92kaRBtUHsqCd32DZBQrLECLJSgcoObFQ3yKpWlYnTr7IPfkevHzOWsx3rXAIFHgMcJyv8GpO41 DH69+lxFGwcKKWwzUXg2VWAkUQMFXeQBqKeH3HFyIwJ3mX4xlvjaTR792imsUa0KrqIQJD87u1W aK6k7Vp8ZL7pJU0tyLd3/UMIX39YrELCqxyu3TMCooLT5LUjWMvyrrXEiw+4cvHZVwG4FFMw0lA y3g/sVrWMBCq7t+kNSATQh+y86xta85wvC2/6s3ArDlJhOt76e/o6DHLW3Bb9Np1E1AtXWiqHs1 xrXmJc+NtNYg95p9IVC3G8JDWLjzq7lGbJiZiRW1fcr/Dc4MG2uvz3MU1j81E/aycAko9beTt3m RSGJhRSgKxJswU61PKa0LDIwFneZMwd5FDAxzPV5vQXRiRyr/UIRiRjc3bnWeF+jPd42Y6MeP0m cexknoxzqS2t9o1QNOUOJdZ X-Google-Smtp-Source: AGHT+IGYUppwEaWsPfSX4i4NKaOHR0JD2a8u6dNdJAItniApagTaLIbMBTLvd60gWgWW97dNmxxQGg== X-Received: by 2002:a05:690c:ed6:b0:786:61c6:7e43 with SMTP id 00721157ae682-78661c6afd0mr63709417b3.35.1762157245982; Mon, 03 Nov 2025 00:07:25 -0800 (PST) Received: from localhost.localdomain (h96-60-249-169.cncrtn.broadband.dynamic.tds.net. [96.60.249.169]) by smtp.gmail.com with UTF8SMTPSA id 00721157ae682-7864ba81de9sm28274367b3.6.2025.11.03.00.07.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Nov 2025 00:07:24 -0800 (PST) From: Demi Marie Obenour Date: Mon, 03 Nov 2025 03:04:55 -0500 Subject: [PATCH v5 1/2] tools: Add adapter tool for services using sd_notify MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20251103-udev-v5-1-5c432ef1ddf8@gmail.com> References: <20251103-udev-v5-0-5c432ef1ddf8@gmail.com> In-Reply-To: <20251103-udev-v5-0-5c432ef1ddf8@gmail.com> To: Spectrum OS Development X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1762157094; l=6031; i=demiobenour@gmail.com; s=20250729; h=from:subject:message-id; bh=ZQ6+gwzBHDR/w9c8KWF1RyZ0rTH+tg9u/sUMdVCd3IY=; b=OcKeQbzaLXJjt5rA0kqbxGsKYRmLL5fohy+xmC1pCG7AztjXrKENq4HMpT1OMOTrztj9IEhX5 uLJM+ALv0AVCpf1MZ7YxZjJHjbH+zTXl88s05LhQT83CAQjxs5tTcRv X-Developer-Key: i=demiobenour@gmail.com; a=ed25519; pk=X57Q4/YQDj9t4SBeKaDwvXYKB6quZJVx/DE2Ly2out0= Message-ID-Hash: OJ5QPGO7VLP7DQ4ZPCSJRIHPE2K67RRE X-Message-ID-Hash: OJ5QPGO7VLP7DQ4ZPCSJRIHPE2K67RRE X-MailFrom: demiobenour@gmail.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; header-match-devel.spectrum-os.org-3; header-match-devel.spectrum-os.org-4; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Demi Marie Obenour , Alyssa Ross X-Mailman-Version: 3.3.9 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: This adapts programs using sd_notify for use with s6 readiness notification. stdin and stdout are hard-coded for simplicity. Signed-off-by: Demi Marie Obenour --- systemd readiness notification has two strict advantages over the s6 version: 1. It allows reliable reloading. 2. It allows providing a status message that the service manager can show in status output. s6 would actually benefit from both of these features. --- Changes since v4: - Use CC0 for the trivial Meson file. - Use -D_GNU_SOURCE instead of #define _GNU_SOURCE 1. - Use a global variable for the iovec. - Use ISC license for the C code in case s6 wants to use it. - Remove unneeded MSG_DONTWAIT. - Remove unneeded check for EAGAIN and EWOULDBLOCK when poll() has already indicated that the file descriptor is ready. Changes since v1: - Hard-code file descriptors. - Run wrapper as background process. - Massively reduce code size. - Use // instead of /* */ for comments. - Check that the notification FD is a pipe and that the listening socket is a socket. - Rely on s6-ipc-socketbinder to create the listening socket. - Do not unlink the listening socket. Signed-off-by: Demi Marie Obenour --- tools/default.nix | 1 + tools/meson.build | 1 + tools/sd-notify-adapter/meson.build | 4 ++ tools/sd-notify-adapter/sd-notify-adapter.c | 107 ++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+) diff --git a/tools/default.nix b/tools/default.nix index 398f57038d3f9fdec47b72850755e289f225f339..36a9a8c84de9f83e31981d3d47fab27e98f6ae5a 100644 --- a/tools/default.nix +++ b/tools/default.nix @@ -76,6 +76,7 @@ stdenv.mkDerivation (finalAttrs: { ./lsvm ./start-vmm ./subprojects + ./sd-notify-adapter ] ++ lib.optionals driverSupport [ ./xdp-forwarder ])); diff --git a/tools/meson.build b/tools/meson.build index 186008dbc9dd2b63adbce7475c375fb0de5c2c6a..5d0ae81042fd3d77646594500f32cb1d48a6af0c 100644 --- a/tools/meson.build +++ b/tools/meson.build @@ -27,6 +27,7 @@ if get_option('host') subdir('lsvm') subdir('start-vmm') + subdir('sd-notify-adapter') endif if get_option('app') diff --git a/tools/sd-notify-adapter/meson.build b/tools/sd-notify-adapter/meson.build new file mode 100644 index 0000000000000000000000000000000000000000..906fbde673105fd65436b34802f1bcc74e9f823e --- /dev/null +++ b/tools/sd-notify-adapter/meson.build @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: CC0-1.0 +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour + +executable('sd-notify-adapter', 'sd-notify-adapter.c', c_args : ['-D_GNU_SOURCE'], install: true) diff --git a/tools/sd-notify-adapter/sd-notify-adapter.c b/tools/sd-notify-adapter/sd-notify-adapter.c new file mode 100644 index 0000000000000000000000000000000000000000..734f018da605e4359d3fa6422a01effbd9e878ea --- /dev/null +++ b/tools/sd-notify-adapter/sd-notify-adapter.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: ISC +// SPDX-FileCopyrightText: 2025 Demi Marie Obenour + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define ARRAY_SIZE(s) (sizeof(s)/sizeof(s[0])) + +enum { + socket_fd, + notification_fd, +}; + +struct iovec msg; + +#define READY "READY=1" +#define READY_SIZE (sizeof(READY) - 1) + +static void process_notification(void) +{ + ssize_t first_recv_size = recv(socket_fd, msg.iov_base, msg.iov_len, + MSG_TRUNC | MSG_PEEK); + if (first_recv_size == -1) { + if (errno == EINTR) + return; // signal caught + err(EXIT_FAILURE, "recv from notification socket"); + } + size_t size = (size_t)first_recv_size; + if (size == 0) + return; // avoid arithmetic on NULL pointer + if (size > msg.iov_len) { + msg.iov_base = realloc(msg.iov_base, size); + if (msg.iov_base == NULL) + err(EXIT_FAILURE, "allocation failure"); + msg.iov_len = size; + } + ssize_t second_recv_size = recv(socket_fd, msg.iov_base, msg.iov_len, + MSG_CMSG_CLOEXEC | MSG_TRUNC); + if (second_recv_size == -1) { + if (errno == EINTR) + return; + err(EXIT_FAILURE, "recv from notification socket"); + } + assert(first_recv_size == second_recv_size); + for (char *next, *cursor = msg.iov_base, *end = cursor + size; + cursor != NULL; cursor = (next == NULL ? NULL : next + 1)) { + next = memchr(cursor, '\n', (size_t)(end - cursor)); + size_t message_size = (size_t)((next == NULL ? end : next) - cursor); + if (message_size == READY_SIZE && + memcmp(cursor, READY, READY_SIZE) == 0) { + ssize_t write_size = write(notification_fd, "\n", 1); + if (write_size != 1) + err(EXIT_FAILURE, "writing to notification descriptor"); + exit(0); + } + } +} + +int main(int argc, char **) +{ + if (argc != 1) + errx(EXIT_FAILURE, "stdin is listening socket, stdout is notification pipe"); + for (;;) { + struct pollfd p[] = { + { + .fd = socket_fd, + .events = POLLIN, + .revents = 0, + }, + { + .fd = notification_fd, + .events = 0, + .revents = 0, + }, + }; + int r = poll(p, ARRAY_SIZE(p), -1); + if (r < 0) { + if (errno == EINTR) + continue; + err(EXIT_FAILURE, "poll"); + } + if (p[0].revents) { + if (p[0].revents & POLLERR) + errx(EXIT_FAILURE, "unexpected POLLERR"); + if (p[0].revents & POLLIN) + process_notification(); + } + if (p[1].revents) + errx(EXIT_FAILURE, "s6 closed its pipe before the child was ready"); + } +} -- 2.51.2