guix-commits
[Top][All Lists]
Advanced

[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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]