[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[shepherd] 05/08: service: 'make-systemd-constructor' supports starting
From: |
Ludovic Courtès |
Subject: |
[shepherd] 05/08: service: 'make-systemd-constructor' supports starting processes eagerly. |
Date: |
Sat, 25 Mar 2023 17:53:07 -0400 (EDT) |
civodul pushed a commit to branch master
in repository shepherd.
commit 558d68065fee4957476e156ba6289a0f92a300f6
Author: Ludovic Courtès <ludo@gnu.org>
AuthorDate: Sat Mar 25 20:09:20 2023 +0100
service: 'make-systemd-constructor' supports starting processes eagerly.
This is useful when the synchronization afforded by socket activation is
welcome, yet we need the process to start right away; an example that
falls into this category is "guix publish --advertise", which should
start right away so it can start advertising itself.
* modules/shepherd/service.scm (make-systemd-constructor): Add #:lazy-start?
parameter and honor it.
* modules/shepherd/support.scm (blocking-port): New procedure.
* tests/systemd.sh: Add 'test-systemd-unix-eager' service and test it.
* doc/shepherd.texi (Service De- and Constructors): Update documentation.
---
doc/shepherd.texi | 4 +++-
modules/shepherd/service.scm | 11 +++++++++--
modules/shepherd/support.scm | 7 +++++++
tests/systemd.sh | 28 ++++++++++++++++++++++++----
4 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/doc/shepherd.texi b/doc/shepherd.texi
index 0277688..bdbf1fe 100644
--- a/doc/shepherd.texi
+++ b/doc/shepherd.texi
@@ -1098,6 +1098,7 @@ The constructor and destructor for systemd-style daemons
are described
below.
@deffn {procedure} make-systemd-constructor @var{command} @var{endpoints} @
+ [#:lazy-start? #t] @
[#:user #f] @
[#:group #f] @
[#:supplementary-groups '()] @
@@ -1110,7 +1111,8 @@ argument, as a systemd-style service listening on
@var{endpoints}, a list of
@code{<endpoint>} objects.
@var{command} is started on demand on the first connection attempt on one of
-@var{endpoints}. It is passed the listening sockets for @var{endpoints} in
+@var{endpoints} when @var{lazy-start?} is true; otherwise it is started as
+soon as possible. It is passed the listening sockets for @var{endpoints} in
file descriptors 3 and above; as such, it is equivalent to an @code{Accept=no}
@uref{https://www.freedesktop.org/software/systemd/man/systemd.socket.html,systemd
socket unit}. The following environment variables are set in its environment:
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index 5b9ae19..4daa9be 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -2003,6 +2003,7 @@ reading."
(define* (make-systemd-constructor command endpoints
#:key
+ (lazy-start? #t)
(user #f)
(group #f)
(supplementary-groups '())
@@ -2018,7 +2019,8 @@ argument, as a systemd-style service listening on
@var{endpoints}, a list of
@code{<endpoint>} objects.
@var{command} is started on demand on the first connection attempt on one of
-@var{endpoints}. It is passed the listening sockets for @var{endpoints} in
+@var{endpoints} when @var{lazy-start?} is true; otherwise it is started as
+soon as possible. It is passed the listening sockets for @var{endpoints} in
file descriptors 3 and above; as such, it is equivalent to an @code{Accept=no}
@uref{https://www.freedesktop.org/software/systemd/man/systemd.socket.html,systemd
socket unit}. The following environment variables are set in its environment:
@@ -2053,7 +2055,12 @@ This must be paired with @code{make-systemd-destructor}."
;; process, once started.
(spawn-fiber
(lambda ()
- (wait-for-readable ports)
+ (if lazy-start?
+ (wait-for-readable ports)
+
+ ;; Hand the child process blocking ports: it may not be ready
+ ;; to handle EAGAIN & co.
+ (for-each blocking-port ports))
(local-output (l10n "Spawning systemd-style service ~a.")
(match command
((program . _) program)))
diff --git a/modules/shepherd/support.scm b/modules/shepherd/support.scm
index 45dfd1f..16ef9ee 100644
--- a/modules/shepherd/support.scm
+++ b/modules/shepherd/support.scm
@@ -45,6 +45,7 @@
report-error
display-line
non-blocking-port
+ blocking-port
user-homedir
user-default-log-file
@@ -278,6 +279,12 @@ There is NO WARRANTY, to the extent permitted by law.")))
(fcntl port F_SETFL (logior O_NONBLOCK flags))
port))
+(define (blocking-port port)
+ "Return PORT after putting it in non-blocking mode."
+ (let ((flags (fcntl port F_GETFL)))
+ (fcntl port F_SETFL (logand (lognot O_NONBLOCK) flags))
+ port))
+
;; Home directory of the user.
diff --git a/tests/systemd.sh b/tests/systemd.sh
index ca9d79b..d5c08a3 100644
--- a/tests/systemd.sh
+++ b/tests/systemd.sh
@@ -1,5 +1,5 @@
# GNU Shepherd --- Test transient services.
-# Copyright © 2022 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2022-2023 Ludovic Courtès <ludo@gnu.org>
#
# This file is part of the GNU Shepherd.
#
@@ -63,7 +63,12 @@ cat > "$conf" <<EOF
#:provides '(test-systemd-unix)
#:start (make-systemd-constructor %command %endpoints)
#:stop (make-systemd-destructor)
- #:respawn? #t))
+ #:respawn? #t)
+ (make <service>
+ #:provides '(test-systemd-unix-eager)
+ #:start (make-systemd-constructor %command %endpoints
+ #:lazy-start? #f)
+ #:stop (make-systemd-destructor)))
EOF
rm -f "$pid"
@@ -98,5 +103,20 @@ do
done
$herd stop test-systemd-unix
-! converse_with_echo_server \
- "(make-socket-address AF_UNIX \"$service_socket\")"
+if converse_with_echo_server "(make-socket-address AF_UNIX
\"$service_socket\")"
+then false; else true; fi
+
+# Now test the eager systemd-style service.
+$herd start test-systemd-unix-eager
+$herd status test-systemd-unix-eager | grep started
+
+# The process should soon be running, before we've tried to connect to it.
+while ! $herd status test-systemd-unix-eager | grep -E "Running value is
[0-9]+"
+do $herd status test-systemd-unix-eager; sleep 0.3; done
+
+child_pid="$($herd status test-systemd-unix-eager | grep Running \
+ | sed '-es/.*Running value is \([0-9]\+\)\./\1/g')"
+kill -0 "$child_pid"
+converse_with_echo_server "(make-socket-address AF_UNIX \"$service_socket\")"
+while ! $herd status test-systemd-unix-eager | grep stopped
+do sleep 0.3; done
- [shepherd] branch master updated (e2d324e -> 353a91b), Ludovic Courtès, 2023/03/25
- [shepherd] 04/08: service: Catch exceptions of essential tasks., Ludovic Courtès, 2023/03/25
- [shepherd] 02/08: shepherd: Define and use 'replace-core-bindings!'., Ludovic Courtès, 2023/03/25
- [shepherd] 07/08: service: Make 'launch-service' private., Ludovic Courtès, 2023/03/25
- [shepherd] 05/08: service: 'make-systemd-constructor' supports starting processes eagerly.,
Ludovic Courtès <=
- [shepherd] 01/08: shepherd: Replace 'primitive-load' with a Scheme implementation., Ludovic Courtès, 2023/03/25
- [shepherd] 06/08: service: Remove redundant condition in 'start'., Ludovic Courtès, 2023/03/25
- [shepherd] 08/08: service: Print "already running" message in 'launch-service', not 'start'., Ludovic Courtès, 2023/03/25
- [shepherd] 03/08: repl: Delete socket before starting., Ludovic Courtès, 2023/03/25