guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[shepherd] 02/02: service: Add #:resource-limits parameter to 'exec-comm


From: Ludovic Courtès
Subject: [shepherd] 02/02: service: Add #:resource-limits parameter to 'exec-command' & co.
Date: Mon, 21 Mar 2022 08:47:00 -0400 (EDT)

civodul pushed a commit to branch master
in repository shepherd.

commit 3ee9a7193d73821d6f1dd76a745ed5e4bb1a78c8
Author: Attila Lendvai <attila@lendvai.name>
AuthorDate: Tue Mar 1 19:12:43 2022 +0100

    service: Add #:resource-limits parameter to 'exec-command' & co.
    
    * modules/shepherd/service.scm (exec-command, fork+exec-command,
    make-forkexec-constructor): Add #:resource-limits and honor it.  Reorder
    keyword args where needed to be uniform.
    * tests/forking-service.sh: Test 'nofile' rlimit.
    * doc/shepherd.texi (Service De- and Constructors): Document 
#:resource-limits.
    
    Co-authored-by: Ludovic Courtès <ludo@gnu.org>
---
 doc/shepherd.texi            | 13 ++++++++++++-
 modules/shepherd/service.scm | 26 ++++++++++++++++++--------
 tests/forking-service.sh     | 15 +++++++++++++--
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/doc/shepherd.texi b/doc/shepherd.texi
index 94f6131..6298e93 100644
--- a/doc/shepherd.texi
+++ b/doc/shepherd.texi
@@ -902,6 +902,7 @@ execution of the @var{command} was successful, @code{#t} if 
not.
   [#:log-file #f] @
   [#:directory (default-service-directory)] @
   [#:file-creation-mask #f] [#:create-session? #t] @
+  [#:resource-limits '()] @
   [#:environment-variables (default-environment-variables)]
 Return a procedure that forks a child process, closes all file
 descriptors except the standard output and standard error descriptors,
@@ -930,6 +931,14 @@ start.
 When @var{log-file} is true, it names the file to which the service's
 standard output and standard error are redirected.  @var{log-file} is
 created if it does not exist, otherwise it is appended to.
+
+Guile's @code{setrlimit} procedure is applied on the entries in
+@var{resource-limits}.  For example, a valid value would be:
+
+@lisp
+'((nproc 10 100)         ;number of processes
+  (nofile 4096 4096))    ;number of open file descriptors
+@end lisp
 @end deffn
 
 @deffn {procedure} make-kill-destructor [@var{signal}]
@@ -953,6 +962,7 @@ procedures.
   [#:log-file #f] @
   [#:directory (default-service-directory)] @
   [#:file-creation-mask #f] [#:create-session? #t] @
+  [#:resource-limits '()] @
   [#:environment-variables (default-environment-variables)]
 @deffnx {procedure} fork+exec-command @var{command} @
   [#:user #f] @
@@ -960,9 +970,10 @@ procedures.
   [#:supplementary-groups '()] @
   [#:directory (default-service-directory)] @
   [#:file-creation-mask #f] [#:create-session? #t] @
+  [#:resource-limits '()] @
   [#:environment-variables (default-environment-variables)]
 Run @var{command} as the current process from @var{directory}, with
-@var{file-creation-mask} if it's true, and with
+@var{file-creation-mask} if it's true, with @var{rlimits}, and with
 @var{environment-variables} (a list of strings like @code{"PATH=/bin"}.)
 File descriptors 1 and 2 are kept as is or redirected to @var{log-file}
 if it's true, whereas file descriptor 0
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm
index ad8608b..600cc95 100644
--- a/modules/shepherd/service.scm
+++ b/modules/shepherd/service.scm
@@ -787,7 +787,8 @@ daemon writing FILE is running in a separate PID namespace."
                        (directory (default-service-directory))
                        (file-creation-mask #f)
                        (create-session? #t)
-                       (environment-variables (default-environment-variables)))
+                       (environment-variables (default-environment-variables))
+                       (resource-limits '()))
   "Run COMMAND as the current process from DIRECTORY, with FILE-CREATION-MASK
 if it's true, and with ENVIRONMENT-VARIABLES (a list of strings like
 \"PATH=/bin\").  File descriptors 1 and 2 are kept as is or redirected to
@@ -795,6 +796,9 @@ LOG-FILE if it's true, whereas file descriptor 0 (standard 
input) points to
 /dev/null; all other file descriptors are closed prior to yielding control to
 COMMAND.  When CREATE-SESSION? is true, call 'setsid' first.
 
+Guile's SETRLIMIT procedure is applied on the entries in RESOURCE-LIMITS.  For
+example, a valid value would be '((nproc 10 100) (nofile 4096 4096)).
+
 By default, COMMAND is run as the current user.  If the USER keyword
 argument is present and not false, change to USER immediately before
 invoking COMMAND.  USER may be a string, indicating a user name, or a
@@ -808,6 +812,8 @@ false."
        ;; Programs such as 'mingetty' expect this.
        (setsid))
 
+     (for-each (cut apply setrlimit <>) resource-limits)
+
      (chdir directory)
      (environ environment-variables)
 
@@ -893,7 +899,8 @@ false."
                             (file-creation-mask #f)
                             (create-session? #t)
                             (environment-variables
-                             (default-environment-variables)))
+                             (default-environment-variables))
+                            (resource-limits '()))
   "Spawn a process that executed COMMAND as per 'exec-command', and return
 its PID."
   ;; Install the SIGCHLD handler if this is the first fork+exec-command call.
@@ -924,7 +931,8 @@ its PID."
                           #:directory directory
                           #:file-creation-mask file-creation-mask
                           #:create-session? create-session?
-                          #:environment-variables environment-variables))
+                          #:environment-variables environment-variables
+                          #:resource-limits resource-limits))
           pid))))
 
 (define* (make-forkexec-constructor command
@@ -932,15 +940,16 @@ its PID."
                                     (user #f)
                                     (group #f)
                                     (supplementary-groups '())
+                                    (log-file #f)
                                     (directory (default-service-directory))
-                                    (environment-variables
-                                     (default-environment-variables))
                                     (file-creation-mask #f)
                                     (create-session? #t)
+                                    (environment-variables
+                                     (default-environment-variables))
+                                    (resource-limits '())
                                     (pid-file #f)
                                     (pid-file-timeout
-                                     (default-pid-file-timeout))
-                                    (log-file #f))
+                                     (default-pid-file-timeout)))
   "Return a procedure that forks a child process, closes all file
 descriptors except the standard output and standard error descriptors, sets
 the current directory to @var{directory}, sets the umask to
@@ -978,7 +987,8 @@ start."
                                   #:file-creation-mask file-creation-mask
                                   #:create-session? create-session?
                                   #:environment-variables
-                                  environment-variables)))
+                                  environment-variables
+                                  #:resource-limits resource-limits)))
       (if pid-file
           (match (read-pid-file pid-file
                                 #:max-delay pid-file-timeout
diff --git a/tests/forking-service.sh b/tests/forking-service.sh
index bd9aac9..4247382 100644
--- a/tests/forking-service.sh
+++ b/tests/forking-service.sh
@@ -25,6 +25,7 @@ conf="t-conf-$$"
 log="t-log-$$"
 pid="t-pid-$$"
 service_pid="t-service-pid-$$"
+service_nofiles="t-service-nofiles-$$"
 service2_pid="t-service2-pid-$$"
 service2_started="t-service2-starts-$$"
 
@@ -49,14 +50,15 @@ cat > "$conf"<<EOF
 (default-pid-file-timeout 10)
 
 (define %command
-  '("$SHELL" "-c" "sleep 600 & echo \$! > $PWD/$service_pid"))
+  '("$SHELL" "-c" "ulimit -n >$PWD/$service_nofiles; sleep 600 & echo \$! > 
$PWD/$service_pid"))
 
 (register-services
  (make <service>
    ;; A service that forks into a different process.
    #:provides '(test)
    #:start (make-forkexec-constructor %command
-                                      #:pid-file "$PWD/$service_pid")
+                                      #:pid-file "$PWD/$service_pid"
+                                      #:resource-limits '((nofile 1567 1567)))
    #:stop  (make-kill-destructor)
    #:respawn? #f))
 
@@ -125,6 +127,15 @@ $herd status test2 | grep started
 test "`cat $PWD/$service2_started`" = "started
 started"
 
+
+
+# test if nofiles was set properly
+test -f "$service_nofiles"
+nofiles_value="`cat $service_nofiles`"
+test 1567 -eq $nofiles_value
+
+
+
 # Try to trigger eventual race conditions, when killing a process between fork
 # and execv calls.
 for i in `seq 1 50`



reply via email to

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