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 4E49E19C13; Thu, 25 Sep 2025 16:54:40 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 6A4B719BF6; Thu, 25 Sep 2025 16:54:38 +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-yx1-xb12d.google.com (mail-yx1-xb12d.google.com [IPv6:2607:f8b0:4864:20::b12d]) by atuin.qyliss.net (Postfix) with ESMTPS id 551D519BF4 for ; Thu, 25 Sep 2025 16:54:34 +0000 (UTC) Received: by mail-yx1-xb12d.google.com with SMTP id 956f58d0204a3-63606491e66so593846d50.2 for ; Thu, 25 Sep 2025 09:54:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1758819273; x=1759424073; darn=spectrum-os.org; h=in-reply-to:autocrypt:from:content-language:references:cc:to :subject:user-agent:mime-version:date:message-id:from:to:cc:subject :date:message-id:reply-to; bh=K16H7hUDV1OjU2cLeBY7xZl3TIUSfjked4LrADffkr8=; b=HUVHdmz7GJUd3L3EOHOufX5rltre2oYcLvQrAQ2o/yi5sdN24WKRa+Df/jOHihcEc1 AKQrdNAVTTyc7+8Vp1SgweQ+WOaLWU7pnRswV2UK9JztY4AcH/6fiX2siS/as3qZGaA2 fK4VtMlJi/mmKGjQG/m1e5GWKgGM7XJOK3Qkck9xrfDrZeHwONqsj34Aws2bXZlFigsz VF0Rtl4kJz4prMQUfuQ40qglBUpZYXWh7xK9szDSunR1zhZPXIGzLbp7pFTib9DqBaMh 954UvD486972Aw7MraSwhPbRVZa4Bz8CInbB8rD+ukf9LiaCX8pfsCDMEI6nCcD2aNgi 0Wqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758819273; x=1759424073; h=in-reply-to:autocrypt:from:content-language:references:cc:to :subject:user-agent:mime-version:date:message-id:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=K16H7hUDV1OjU2cLeBY7xZl3TIUSfjked4LrADffkr8=; b=nMhYzJIO243NVw+T9VcJnH8JEBrnF8QvJDqIJAQYggN/v9ESKiu90MrZ+etZKrtrDE qVdV6c25LzdbW6MzgK4JTxoFdgYfuSOI5Q9mnNytxxfqWlDGIVeH+dguzrBrTzYDos1m OqBNNziJRVuV51pvctp0lHPX+qmQcg1kpa7Uz7p52OF371XuE3WIYBeNpJg3LwoWn/HY Y65d5PtzygQSzZYnEyfMHpOOpVemgFwvNuQO4CzjpbqFaYTpdBL3YBqRAMp4q8NU4kPh yn12zGtFIS75bmzn+GSQi3fjZE/7S5rzLFHhS03ZrKLa6guXhoPvwezTtZucnekUAaNZ VdDQ== X-Gm-Message-State: AOJu0Yxdzvd7yDf4fanUcflJUwF+a6nTxv5ztULg3N3LUpMjq+XEYgtb /tOhdQh7ZlWcyCEKlrCg6CItAirCACTYewkK4JilugN01XcCtyOLsak9OYhWPw== X-Gm-Gg: ASbGncuU5+Wr97zvXQ6nxbcLbKRJ/H9nDgJbTkE+bga0XZxZtZDGaH7/IkcKXlXIQcT dMjtEHaDuSafhYqLpjlmhhv91OTlH1/WiK2eozQ7Rvy1kgE7BO0bzevbZk8WCoT2nGheIlIbB4J ayI+UrCB8g5Dm08eoTCa7YBa6gicTvswG39WR1iY7tcDs76C26Pdfw/7SGq+c0S9sglb3/Cbw7u 2m+Rysbhj+E4fqIU0RK8iKFZtH2oD6ffc0RIVz1V+eDKMFcJGbAP4IpW40O1ISaqs3WOHPDuhyu 6h+DfXWFEywE//y+V2DxoFNSjfAzZ1rna7zKFg2yfkqYci5qCYGT/VpUMdGZQMv41xzdsyshfX+ 0d1W3oD58rQcBFkRou8g+sKp0gYhbCdUUsfmdlDmX003sohUdi/RGEcBV/VQrTIe77tHRg/8JNd +rwM6GfNLlUBsGWBYw6XbENsjzj/CRwqB5hNc= X-Google-Smtp-Source: AGHT+IG1/R4bzalYTseFMeOD3zbTz7a7xhfTitAzfJjnCIKYOn9DR9sHEk1Gm6y3OVpcYxfzJPRpKw== X-Received: by 2002:a05:6902:6b0e:b0:ea3:f937:a52a with SMTP id 3f1490d57ef6-eb37fcabee8mr3871617276.24.1758819272404; Thu, 25 Sep 2025 09:54:32 -0700 (PDT) Received: from [10.138.34.110] (h96-60-249-169.cncrtn.broadband.dynamic.tds.net. [96.60.249.169]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-eb38393c76bsm780123276.25.2025.09.25.09.54.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 25 Sep 2025 09:54:31 -0700 (PDT) Message-ID: <222174e7-a743-497a-8d04-1c35ed2abc0f@gmail.com> Date: Thu, 25 Sep 2025 12:54:27 -0400 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v2 1/3] tools: Add adapter tool for services using sd_notify To: Alyssa Ross References: <20250924-udev-v2-0-6089de521b3b@gmail.com> <20250924-udev-v2-1-6089de521b3b@gmail.com> <87348addvj.fsf@alyssa.is> Content-Language: en-US From: Demi Marie Obenour Autocrypt: addr=demiobenour@gmail.com; keydata= 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 +MYSfkEjBz0E8CLOcAw7JIwAaeBT In-Reply-To: <87348addvj.fsf@alyssa.is> Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="------------0fwDV9thFHW2qe5XS0lVRSvi" Message-ID-Hash: KYL47QLH2KVPKGOVQX7BDSOHYAHZGAEM X-Message-ID-Hash: KYL47QLH2KVPKGOVQX7BDSOHYAHZGAEM 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: Spectrum OS Development 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 is an OpenPGP/MIME signed message (RFC 4880 and 3156) --------------0fwDV9thFHW2qe5XS0lVRSvi Content-Type: multipart/mixed; boundary="------------ZFQAbqltffNOHj313SkKidTc"; protected-headers="v1" From: Demi Marie Obenour To: Alyssa Ross Cc: Spectrum OS Development Message-ID: <222174e7-a743-497a-8d04-1c35ed2abc0f@gmail.com> Subject: Re: [PATCH v2 1/3] tools: Add adapter tool for services using sd_notify References: <20250924-udev-v2-0-6089de521b3b@gmail.com> <20250924-udev-v2-1-6089de521b3b@gmail.com> <87348addvj.fsf@alyssa.is> In-Reply-To: <87348addvj.fsf@alyssa.is> Autocrypt-Gossip: addr=hi@alyssa.is; keydata= xsFNBFpSgoYBEAC4xkCYidG2JlRWulUkTWcx0pHFDf3oSbb6Q872Kb3iDChWgluNVz43hva1 3xfDo9foV0GoyfGl/ycSCkXX5hlQr7ir/5FN38E7H/yY6tH8+l68iDgIOcb1qY0OYaxyg+Lz WesfFQedrmwNTbF4L1BtWzrTR5PflDdhDo5VWSguHGJFSclchcr/6UmMb/gOUN+2ElBC2TE2 EKY099phZ6DJZ2aZCsclwKIdCpZzXlEmXPAeaH5om6xo90JYv5+sFji40R0Plqec3WC+jTxy lGca6IbPdOminuUF+GvsR86eVsgh/0XNK7/zus7gyc4PuMUA1rCoeHcWOBDPgmelgCQyJGXd /bXeKuUsGoge58uc7/YNvOh1vfpD3AaEMqAyXfmmUwBnIicml74+2eOpH3Oljfs01g+DhkOB MtpVSZSgaIDvP0WG6cbAxImoUasnmNxEDNskfVmI8bsajPW9bt4z5hiP5Q9G3vE0D5HcIFdM adOz81PpOwNiUXcjtYV1PWZQ56jbSTOf8EBvsB71WwB+XgVWcPzIlY8hAykiHIO87oV3o71U JTAn1Foj7mjSADnY0deleOmar/K5jrK3wvKKM1XlB7PXcGBdkorJC+cbxVsw0ADzMw0c7bVc wEE7OFvHjQiIK1lO+lb1cvGBBY3IZxjsjZdA/VsFHFdAeYlzNQARAQABzRpBbHlzc2EgUm9z cyA8aGlAYWx5c3NhLmlzPsLBlwQTAQgAQQIbAwULCQgHAgYVCAkKCwIEFgIDAQIeAQIXgAIZ ARYhBHVzVtd5u7iIdz5BXnNszfnvUb2XBQJoh9HmBQkOtoJgAAoJEHNszfnvUb2XFxAP/jF7 Rxuspytz7VwOA/y5WQe/FdPNRvyRUzj66ZzfuaG++md14LWcrvbb2hHLdS5ePdKoOaqC3xhK Ncy/5RVd4pD5N4AY7O5228JKDO8GGWEl3rupOCmYQL9P8GpsdGt2xkFqbu4HrFzMTzl6nvKN GtvhBSCkAW3v7wTwPf2rkjX8f+clmRZn4YLfojaBCT/ZFjmJkQSWZ+2rUZOxjgZgckLkplu8 LVILVdaHNLkOrxbKQLuuVyEkN+/YrshyJP4a7Z/Tnw+3eZcaLuLOxBHpWOAAgJZ8kL+V7BxK DlTywv/OOr0CoNi9zjH3VgRiJ1961K/DocjA50pWBilMUs4jGp9omhkAOwdNV2hi+Zj/GXaD kgvBlE313DGWzgW0RauL8j5/GULgphwm5UOHXb/5yM9pRw87kfQ/+zQuHpguoXSGkUv0kSID 88kUGlNxy1kkTsSYG2UTKLmLDPuUGOUDGaNUzD+J49MogSLTmvHUIYNs0jFmpLyhVoTtSi/I VQQpHyk9ucAZd2OLxChm3RBJhAbmGw3rhUxx6B8SHwcBcJDttGyYF2GZj9AYAGlU/Fm1Itoi NwJD0vQnSZ//25l+XJehpeeixsqydj00gksHWEFaIEgCYyC6JfmGS4HtuUcv76vc2vLCv5aH hJVHHKGs+kiKJ2+r7bCNwvW0doVePdByzjgEZyd/yxIKKwYBBAGXVQEFAQEHQCVxoiHOlsEo NDKGCbxg4nL3E1CV0MRQCU1hPowd77h3AwEIB8LBfAQYAQoAJgIbDBYhBHVzVtd5u7iIdz5B XnNszfnvUb2XBQJoh9HXBQkB4YUCAAoJEHNszfnvUb2XgvAP+gIIKR3KatmwuUcla1RN6tUc 0Ae9eqS1cbSEDj8a14fnvUHtlCEO5g4m2PvPn7L2o7047ppl5100+zGMocXWslnDFJJVeAOp xzlhZ48DFMxkZkjtLY2fRrj1tOtzrTRikV0/UsaVs9tMPMEsVu/FH0exMoNELcqEVUgcRRpd XYXC9zgDUcM4+JRH8hDOiC51JRvdkXcokAXphuCY3J996i8Ph+kg6xMqscePscvvltR68jcT HHDOiOQtzjJRKQ6BHUzYdIRixcq210sabfZGJVT+7BfHI5qiUwfoG3DXSJygviN3I/EfnSbD 6T0Ccv/G6wQPHO4Vyn+egrMOU/HUrCKuq/b0rYvI8pTtRWAxIHkFZoKVB8I8Rl8+riGiEUAh Ja0bU4iOg7vR5Bm8Gt/tR6KjClyBI5NN1M1haFgVXqZ3dsQDpBjivbDHbUsAXVsd00y0B4Ir 8muvII9eJOwbTyqcG9RJbflquPp+FPlgiy9pYj52PB0NwzLYqX0fOWU8IqQF3bWtdJIb4Zat XnfqYtJ/wCaJTU43N3+/TIdqNA4G3WbyRYsCnz/kkf1ARmxoq3r29dOl8OnNHEvB1+hBlNBk d+cLpsYdTxa63OpbNDpm/unX1sEpOYy04dL5Y8B1Xbh+rQFNySq4Ani2dl5N1OsrjgzZ+wkl k2wOTWzl7wFH --------------ZFQAbqltffNOHj313SkKidTc Content-Type: multipart/mixed; boundary="------------KDhEJEGOWkhS8dpdyaBsVV29" --------------KDhEJEGOWkhS8dpdyaBsVV29 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On 9/25/25 06:29, Alyssa Ross wrote: > Demi Marie Obenour writes: >=20 >> This adapts programs using sd_notify for use with s6 readiness >> notification. >> >> I chose to use Linux-specific epoll(7). It makes the code simpler and= >> more readable. Also, stdin and stdout are hardcoded. This is in the >> interest of simplicity. >=20 > I personally find poll to be more readable when working with a fixed se= t > of descriptors, but it's up to you! poll can actually fail with ENOMEM, which is one of the reasons I used epoll. >> >> 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 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 sock= et >> is a socket. >> - Rely on s6-ipc-socketbinder to create the listening socket. >> - Do not unlink the listening socket. >> --- >> tools/default.nix | 1 + >> tools/meson.build | 1 + >> tools/sd-notify-adapter/meson.build | 4 + >> tools/sd-notify-adapter/sd-notify-adapter.c | 206 +++++++++++++++++++= +++++++++ >> 4 files changed, 212 insertions(+) >> >> diff --git a/tools/sd-notify-adapter/meson.build b/tools/sd-notify-ada= pter/meson.build >> new file mode 100644 >> index 0000000000000000000000000000000000000000..6032a3a7704d49cae0655b= 43d0189444d3b15e4d >> --- /dev/null >> +++ b/tools/sd-notify-adapter/meson.build >> @@ -0,0 +1,4 @@ >> +# SPDX-License-Identifier: ISC >> +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour >> + >> +executable('sd-notify-adapter', 'sd-notify-adapter.c', install: true)= >=20 > Why the non-standard license? Mistake :) >> diff --git a/tools/sd-notify-adapter/sd-notify-adapter.c b/tools/sd-no= tify-adapter/sd-notify-adapter.c >> new file mode 100644 >> index 0000000000000000000000000000000000000000..661e3f41e57dae97a5cfae= b3a7088b0c67235563 >> --- /dev/null >> +++ b/tools/sd-notify-adapter/sd-notify-adapter.c >> @@ -0,0 +1,206 @@ >> +// SPDX-License-Identifier: MIT >> +// SPDX-FileCopyrightText: 2025 Demi Marie Obenour >> +// check_posix and check_posix_bool are based on playpen.c, which has= >> +// the license: >> +// >> +// Copyright 2014 Daniel Micay >> +// >> +// Permission is hereby granted, free of charge, to any person obtain= ing a >> +// copy of this software and associated documentation files (the >> +// "Software"), to deal in the Software without restriction, includin= g >> +// without limitation the rights to use, copy, modify, merge, publish= , >> +// distribute, sublicense, and/or sell copies of the Software, and to= >> +// permit persons to whom the Software is furnished to do so, subject= to >> +// the following conditions: >> +// >> +// The above copyright notice and this permission notice shall be inc= luded >> +// in all copies or substantial portions of the Software. >> +// >> +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EX= PRESS >> +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF >> +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEM= ENT. >> +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR A= NY >> +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRAC= T, >> +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE >> +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. >> + >> +#define _GNU_SOURCE 1 >> +#include >> +#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])) >> + >> +// TODO: does this need to have credit given to Daniel Micay? >> +[[gnu::format(printf, 2, 3), gnu::warn_unused_result]] >> +static intmax_t check_posix(intmax_t arg, const char *fmt, ...) { >> + if (arg >=3D 0) >> + return arg; >> + assert(arg =3D=3D -1); >> + va_list a; >> + va_start(a, fmt); >> + verr(EX_OSERR, fmt, a); >> +} >> + >> +#define check_posix(arg, message, ...) \ >> + ((__typeof__(arg))check_posix(arg, message, ## __VA_ARGS__)) >> + >> +// And same here >> +[[gnu::format(printf, 2, 3)]] >> +static void check_posix_bool(intmax_t arg, const char *fmt, ...) { >> + if (arg !=3D -1) { >> + assert(arg =3D=3D 0); >> + return; >> + } >> + va_list a; >> + va_start(a, fmt); >> + verr(EX_OSERR, fmt, a); >> + va_end(a); // Not reached >> +} >=20 > I would prefer that we do manual error checks in the style of other C > code in Spectrum. Then we don't have to worry about licensing of these= > helpers, and also don't have the problem of how to share them between > multiple files later on. It's likely that readers are also going to be= > more familiar with simple error checks. Will change. >> + >> +static bool ready; >> + >> +enum { >> + socket_fd, >> + notification_fd, >> +}; >> + >> +static void >> +process_notification(struct iovec *const msg, const char *const initi= al_buffer) { >> + ssize_t data =3D recv(socket_fd, msg->iov_base, msg->iov_len, >> + MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK); >> + if (data =3D=3D -1) { >> + if (errno =3D=3D EINTR) { >> + return; // signal caught >> + } >> + if (errno =3D=3D EAGAIN || errno =3D=3D EWOULDBLOCK) { >> + return; // spurious wakeup >> + } >> + } >> + size_t size =3D (size_t)check_posix(data, "recv"); >> + if (size > (size_t)INT_MAX) { >> + // cannot happen on Linux, don't bother implementing >> + size =3D (size_t)INT_MAX; >> + } >=20 > If it can't happen, why do we branch on it? G >> + if (size > msg->iov_len) { >> + char *b =3D (msg->iov_base =3D=3D initial_buffer) ? >> + malloc(size) : realloc(msg->iov_base, size); >> + if (b !=3D NULL) { >> + msg->iov_base =3D b; >> + msg->iov_len =3D size; >> + } >> + } >=20 > Wouldn't it be simpler to pass an empty iov, then allocate whatever siz= e > we need here, than to have to handle sometimes having a stack-allocated= > buffer and sometimes not? It would >> + size =3D (size_t)check_posix(recv(socket_fd, msg->iov_base, msg->iov= _len, >> + MSG_CMSG_CLOEXEC | MSG_DONTWAIT | MS= G_TRUNC), >> + "recv"); >> + const char *cursor =3D msg->iov_base; >> + const char *const end =3D cursor + size; >> + for (char *next; cursor !=3D NULL; cursor =3D (next =3D=3D NULL ? NU= LL : next + 1)) { >> + next =3D memchr(cursor, '\n', (size_t)(end - cursor)); >> + size_t message_size =3D (size_t)((next =3D=3D NULL ? end : next) - = cursor); >> + >> + // TODO: avoid repeating sizeof(string) >=20 > Yeah, let's maybe pull the message we're looking for out into a constan= t. I agree. >> + if (message_size =3D=3D sizeof("READY=3D1") - 1 && >> + memcmp(cursor, "READY=3D1", sizeof("READY=3D1") - 1) =3D=3D 0) = { >> + if (check_posix(write(notification_fd, "\n", 1), "write") !=3D 1) >> + assert(0); >> + exit(0); >> + } >> + } >> +} >> + >> +int main(int argc, char **argv [[gnu::unused]]) { >> + if (argc !=3D 1) { >> + errx(EX_USAGE, "stdin is listening socket, stdout is notification p= ipe"); >> + } >> + struct stat info; >> + check_posix_bool(fstat(notification_fd, &info), "fstat"); >> + if (!S_ISFIFO(info.st_mode)) { >> + errx(EX_USAGE, "notification descriptor is not a pipe"); >> + } >> + int value; >> + socklen_t len =3D sizeof(value); >> + int status =3D getsockopt(socket_fd, SOL_SOCKET, SO_DOMAIN, &value, = &len); >> + if (status =3D=3D -1 && errno =3D=3D ENOTSOCK) { >> + errx(EX_USAGE, "socket fd is not a socket"); >> + } >> + check_posix_bool(status, "getsockopt"); >> + assert(len =3D=3D sizeof(value)); >> + if (value !=3D AF_UNIX) { >> + errx(EX_USAGE, "socket fd must be AF_UNIX socket"); >> + } >> + check_posix_bool(getsockopt(socket_fd, SOL_SOCKET, SO_TYPE, &value, = &len), >> + "getsockopt"); >> + assert(len =3D=3D sizeof(value)); >> + if (value !=3D SOCK_DGRAM) { >> + errx(EX_USAGE, "socket must be datagram socket"); >> + } >> + >=20 > I think these checks are overly defensive. It's going to be very > difficult to use this program wrong given it's always going to be used > in the same way in run scripts. I'd rather have less code, which will > make it easier to understand what the actual functionality of the > program is. Will fix. >> + // Ignore SIGPIPE. >> + struct sigaction act =3D { }; >> + act.sa_handler =3D SIG_IGN; >> + check_posix_bool(sigaction(SIGPIPE, &act, NULL), "sigaction(SIGPIPE)= "); >=20 > Wouldn't SIGPIPE be useful here? Isn't the default behavior of exiting= > on SIGPIPE exactly what we'd want to do? Good point. I should ignore SIGPIPE in the run script, though. systemd does this by default. >> + >> + // Open file descriptors. >> + int epoll_fd =3D check_posix(epoll_create1(EPOLL_CLOEXEC), "epoll_cr= eate1"); >> + if (epoll_fd < 3) { >> + errx(EX_USAGE, "Invoked with file descriptor 0, 1, or 2 closed"); >> + } >> + struct epoll_event event =3D { .events =3D EPOLLIN, .data.u64 =3D so= cket_fd }; >> + check_posix_bool(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket_fd, &even= t), >> + "epoll_ctl"); >> + event =3D (struct epoll_event) { .events =3D 0, .data.u64 =3D notifi= cation_fd }; >> + check_posix_bool(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, notification_fd,= &event), >> + "epoll_ctl"); >> + >> + // Main event loop. >> + char buf[sizeof("READY=3D1\n") - 1]; >> + struct iovec v =3D { >> + .iov_base =3D buf, >> + .iov_len =3D sizeof(buf), >> + }; >> + for (;;) { >> + struct epoll_event out_event[2] =3D {}; >> + int epoll_wait_result =3D >> + check_posix(epoll_wait(epoll_fd, out_event, ARRAY_SIZE(out_event),= -1), >> + "epoll_wait"); >> + for (int i =3D 0; i < epoll_wait_result; ++i) { >> + switch (out_event[i].data.u64) { >> + case socket_fd: >> + if (out_event[i].events !=3D EPOLLIN) { >> + errx(EX_PROTOCOL, "Unexpected event from epoll() on notification= socket"); >> + } >> + process_notification(&v, buf); >> + break; >> + case notification_fd: >> + if (out_event[i].events !=3D EPOLLERR) { >> + errx(EX_SOFTWARE, "Unexpected event from epoll() on supervison p= ipe"); >> + } >> + if (ready) { >> + // Normal exit >> + return 0; >> + } >> + errx(EX_PROTOCOL, "s6 closed its pipe before the child was ready"= ); >> + break; >=20 > Why do we need to poll on notification_fd at all? If it closes early, > we get a write fail or a SIGPIPE, and we exit with a failure or are > killed, which is fine, right? If it closes early, but systemd-udevd never sends READY=3D1, the program uselessly hangs around. --=20 Sincerely, Demi Marie Obenour (she/her/hers) --------------KDhEJEGOWkhS8dpdyaBsVV29 Content-Type: application/pgp-keys; name="OpenPGP_0xB288B55FFF9C22C1.asc" Content-Disposition: attachment; filename="OpenPGP_0xB288B55FFF9C22C1.asc" Content-Description: OpenPGP public key Content-Transfer-Encoding: quoted-printable -----BEGIN PGP PUBLIC KEY BLOCK----- xsFNBFp+A0oBEADffj6anl9/BHhUSxGTICeVl2tob7hPDdhHNgPR4C8xlYt5q49y B+l2nipdaq+4Gk6FZfqC825TKl7eRpUjMriwle4r3R0ydSIGcy4M6eb0IcxmuPYf bWpr/si88QKgyGSVZ7GeNW1UnzTdhYHuFlk8dBSmB1fzhEYEk0RcJqg4AKoq6/3/ UorR+FaSuVwT7rqzGrTlscnTDlPWgRzrQ3jssesI7sZLm82E3pJSgaUoCdCOlL7M MPCJwI8JpPlBedRpe9tfVyfu3euTPLPxwcV3L/cfWPGSL4PofBtB8NUU6QwYiQ9H zx4xOyn67zW73/G0Q2vPPRst8LBDqlxLjbtx/WLR6h3nBc3eyuZ+q62HS1pJ5EvU T1vjyJ1ySrqtUXWQ4XlZyoEFUfpJxJoN0A9HCxmHGVckzTRl5FMWo8TCniHynNXs BtDQbabt7aNEOaAJdE7to0AH3T/Bvwzcp0ZJtBk0EM6YeMLtotUut7h2Bkg1b//r 6bTBswMBXVJ5H44Qf0+eKeUg7whSC9qpYOzzrm7+0r9F5u3qF8ZTx55TJc2g656C 9a1P1MYVysLvkLvS4H+crmxA/i08Tc1h+x9RRvqba4lSzZ6/Tmt60DPM5Sc4R0nS m9BBff0Nm0bSNRS8InXdO1Aq3362QKX2NOwcL5YaStwODNyZUqF7izjK4QARAQAB zTxEZW1pIE9iZW5vdXIgKElUTCBFbWFpbCBLZXkpIDxhdGhlbmFAaW52aXNpYmxl dGhpbmdzbGFiLmNvbT7CwY4EEwEIADgWIQR2h02fEza6IlkHHHGyiLVf/5wiwQUC X6YJvQIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRCyiLVf/5wiwWRhD/0Y R+YYC5Kduv/2LBgQJIygMsFiRHbR4+tWXuTFqgrxxFSlMktZ6gQrQCWe38WnOXkB oY6n/5lSJdfnuGd2UagZ/9dkaGMUkqt+5WshLFly4BnP7pSsWReKgMP7etRTwn3S zk1OwFx2lzY1EnnconPLfPBc6rWG2moA6l0WX+3WNR1B1ndqpl2hPSjT2jUCBWDV rGOUSX7r5f1WgtBeNYnEXPBCUUM51pFGESmfHIXQrqFDA7nBNiIVFDJTmQzuEqIy Jl67pKNgooij5mKzRhFKHfjLRAH4mmWZlB9UjDStAfFBAoDFHwd1HL5VQCNQdqEc /9lZDApqWuCPadZN+pGouqLysesIYsNxUhJ7dtWOWHl0vs7/3qkWmWun/2uOJMQh ra2u8nA9g91FbOobWqjrDd6x3ZJoGQf4zLqjmn/P514gb697788e573WN/MpQ5XI Fl7aM2d6/GJiq6LC9T2gSUW4rbPBiqOCeiUx7Kd/sVm41p9TOA7fEG4bYddCfDsN xaQJH6VRK3NOuBUGeL+iQEVF5Xs6Yp+U+jwvv2M5Lel3EqAYo5xXTx4ls0xaxDCu fudcAh8CMMqx3fguSb7Mi31WlnZpk0fDuWQVNKyDP7lYpwc4nCCGNKCj622ZSocH AcQmX28L8pJdLYacv9pU3jPy4fHcQYvmTavTqowGnM08RGVtaSBNYXJpZSBPYmVu b3VyIChsb3ZlciBvZiBjb2RpbmcpIDxkZW1pb2Jlbm91ckBnbWFpbC5jb20+wsF4 BBMBAgAiBQJafgNKAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCyiLVf /5wiwYa/EACv8a2+MMou9cSCNoZBQaU+fTmyzft9hUE+0d5W2UY1RY3OsjFIzm9R /4SVccfsqOYLEo+S0vQMIIIqFEq3FCpXXwPzyimotps05VA8U3Bd7yseojFygOgK sAMOAee2RCaDDOnoJue01dfZMzzHPO/TVdp3OvnpWipfv5G1Xg96rwbhMLE3tg6N xwAHa31Bv4/Xq8CJOoIWvx6fcmZQpz01/lSvsYn0KrfEbTKkuUf0vM9JrCTCP2oz VNN5BYzqaq2M4r+jmSyeXLim922VOWqGkUEQ85BSEemqrRS06IU6NtEMsF8EWt/b hWjk/9GDKTcnpdJHTrMxTspExBiNrvpI2t+YPU5B/dJJAUxvmhFrbSIbdB8umBZs I3AMYrEmpAbh5x7jEjoskUC7uN3o9vpg1oCLS2ePDLtAtyBtbHnkA4xGD7ar8mem xpH9lY/i+sC6CyyIUWcUDnnagKyJP0m9ks0GLsTeOCA0bft2XA6rD6aaCnMUsndT ctrab42CV5XypjmC4U1rPJ8JQJUh1/3P48/8sMH+3krxpJ06KNWNFaUbaMTGiltZ 7x9DngklSYrX0T+2G4kVXNmjaljwkoLahwLla2gUWwBSyofXdqyhQdwZsp01KXNQ UCyT/Pg+aDcm/E7OMV3d4lf7g/CSxiX2GSEe6BlhSz+Lmd7ZJ3g32M1ARGVtaSBN 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 EtJuZYM5blWncBOJCoWMnBEcTEo/viU3GgcVRw=3D=3D =3Dx94R -----END PGP PUBLIC KEY BLOCK----- --------------KDhEJEGOWkhS8dpdyaBsVV29-- --------------ZFQAbqltffNOHj313SkKidTc-- --------------0fwDV9thFHW2qe5XS0lVRSvi Content-Type: application/pgp-signature; name="OpenPGP_signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="OpenPGP_signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEopQtqVJW1aeuo9/sszaHOrMp8lMFAmjVc8QACgkQszaHOrMp 8lN1Cw/+LdJPTvF6EMyhxlhJjS2jgCuaVXtKNuHxidesRjyDJWvlnROF19f2yIvX 2VkKAtrcV2KgfEj4yN1ELFvnxGiGrR7Z5ailyVR/K0saP+Ql+Dwe/h35b2xRNERt zMGpp8hrKjCBo7RzX0IftHMBFL3ROe54tUhrU/CKrQ5tueSqawbmwU7pPVHM9874 vBqr2viX8KlpjQrFXM6SphoimPJMcZHG6ZL65nvfZJ5YEdNNpnxpLHHNuOOR2AVZ WjPabYHsZkmxTXgRLEjH2/HHrPE2vpBhB5fexhYEIqSJepu2CbACMyzkVg7+qnw8 fnF8loaRmZvGNz3f2ztfhMqHdTOCWOz0wXmZipA0jrqNGIlOy1ZkFkgU/pwzEztq bWzvnXiMGObAyGm+m3g14iWzQh22vWeyDwBnv88moJTFy8reFpQLSWh2YuCYlk8V lvWS6et4RtiasaOBWdUC1jEIouHrY34Z75wLnI3pXp43xxqH528F+9vo8ierz7hd pyIGdF2iYhxuAK4Up9UOGKiJie5sI8uCr6IoDj/iaYNl3x00wbEplNieae9QpEDg vuGjl9iZ2+iSfgsL8vI/+rYG5Ngq/KJ853eQ4hfmI+dpkNX1FYVQQGdba5s/I7/c +q6qdcVdvv5a0I3fA0dVfd3gMgckr9BbTWCxaJrBxhgPgQoipkU= =JXRf -----END PGP SIGNATURE----- --------------0fwDV9thFHW2qe5XS0lVRSvi--