Message ID | 20220301070615.21028-1-attila@lendvai.name |
---|---|
State | Accepted |
Headers | show |
Series | [bug#54205,Shepherd] Factor out a public CALL-IN-FORK. | expand |
Context | Check | Description |
---|---|---|
cbaines/applying patch | fail | View Laminar job |
cbaines/issue | success | View issue |
Attila Lendvai schreef op di 01-03-2022 om 08:06 [+0100]: > their service is started. One such example is calling setrlimit from a start > action to set NOFILE (the open files limit), before the service is exec'ed and > thus inherits this value from the parent process, i.e. from Shepherd. 'fork+exec-command' already accepts a 'environment-variables' and 'file-creation-mask', how about adding an 'open-file-limit' argument? To me, that seems more declarative and less fragile than having to call 'call-in-fork' manually in a 'start' procedure (*). Support for other rlimits can be added on an as-needed basis. Alternatively, the argument could be generalised to a more general 'rlimit' argument: #:rlimits `((,RLIMIT_AS ,SOFT ,HARD) (,RLIMIT_NPROC ,SOFT ,HARD) (,RLIMIT_NOFILE ,SOFT ,HARD)) WDYT? Greetings, Maxime. (*) E.g., one of the ideas for making shepherd faster, was using some kind of multi-threading. Forking when multi-threading is ill-defined (see POSIX) though, so some kind of zygote process + IPC might be necessary (http://neugierig.org/software/chromium/notes/2011/08/zygote.html has a nice explanation on zygote processes, the bits about software updates can be ignored here).
Hi, Maxime Devos <maximedevos@telenet.be> skribis: > Attila Lendvai schreef op di 01-03-2022 om 08:06 [+0100]: >> their service is started. One such example is calling setrlimit from a start >> action to set NOFILE (the open files limit), before the service is exec'ed and >> thus inherits this value from the parent process, i.e. from Shepherd. > > 'fork+exec-command' already accepts a 'environment-variables' and > 'file-creation-mask', how about adding an 'open-file-limit' argument? > To me, that seems more declarative and less fragile than having > to call 'call-in-fork' manually in a 'start' procedure (*). Seconded. > Support for other rlimits can be added on an as-needed basis. > Alternatively, the argument could be generalised to a more general > 'rlimit' argument: > > #:rlimits > `((,RLIMIT_AS ,SOFT ,HARD) > (,RLIMIT_NPROC ,SOFT ,HARD) > (,RLIMIT_NOFILE ,SOFT ,HARD)) > > WDYT? This interface brings more flexibility, I’m all for it. > (*) E.g., one of the ideas for making shepherd faster, was using some > kind of multi-threading. Forking when multi-threading is ill-defined I think what we need is concurrency, not POSIX threads. IOW, we can achieve the concurrency we need without resorting to POSIX threads, for example using Fibers on a single POSIX thread. Thanks, Ludo’.
Ludovic Courtès schreef op wo 02-03-2022 om 17:05 [+0100]: > I think what we need is concurrency, not POSIX threads. IOW, we can > achieve the concurrency we need without resorting to POSIX threads, for > example using Fibers on a single POSIX thread. guile-fibers uses threads internally, e.g. in (fibers interrupts). Interrupts can theoretically be avoided, but that has a downside that if a start procedure goes into infinite loop (while forgetting to sleep), the whole shepherd would hang. I'm not saying that we need POSIX threads per-se -- I find 'choice-operation', 'perform-operation', the channel operations and Fibers conditions much more convenient than the (lack of) POSIX equivalents, but I'd prefer avoiding the assumption of single-threading where feasible, to make it ourselves not harder than necessary in the future, in case it turns out we need POSIX threading somewhere (even if only as an implementation detail). Greetings, Maxime.
> > Support for other rlimits can be added on an as-needed basis. > > > > Alternatively, the argument could be generalised to a more general > > 'rlimit' argument: > > > > #:rlimits > > `((,RLIMIT_AS ,SOFT ,HARD) > > (,RLIMIT_NPROC ,SOFT ,HARD) > > (,RLIMIT_NOFILE ,SOFT ,HARD)) > > > > WDYT? > > This interface brings more flexibility, I’m all for it. FTR, i've filed this as a patch (with a test!). https://issues.guix.gnu.org/54215 -- • attila lendvai • PGP: 963F 5D5F 45C7 DFCD 0A39 -- “It is a miracle that curiosity survives formal education. It is a very grave mistake to think that the enjoyment of seeing and searching can be promoted by means of coercion and a sense of duty.” — Albert Einstein (1879–1955), 'Autobiographical Notes' (1949), slightly paraphrased
Attila Lendvai <attila@lendvai.name> skribis: > FTR, i've filed this as a patch (with a test!). > > https://issues.guix.gnu.org/54215 Awesome, closing this one! Ludo’.
diff --git a/modules/shepherd/service.scm b/modules/shepherd/service.scm index ad8608b..8d5e30f 100644 --- a/modules/shepherd/service.scm +++ b/modules/shepherd/service.scm @@ -79,6 +79,7 @@ make-forkexec-constructor make-kill-destructor exec-command + fork-and-call fork+exec-command default-pid-file-timeout read-pid-file @@ -883,19 +884,8 @@ false." ;; Signals that the shepherd process handles. (list SIGCHLD SIGINT SIGHUP SIGTERM)) -(define* (fork+exec-command command - #:key - (user #f) - (group #f) - (supplementary-groups '()) - (log-file #f) - (directory (default-service-directory)) - (file-creation-mask #f) - (create-session? #t) - (environment-variables - (default-environment-variables))) - "Spawn a process that executed COMMAND as per 'exec-command', and return -its PID." +(define* (fork-and-call thunk) + "Call THUNK in a fork." ;; Install the SIGCHLD handler if this is the first fork+exec-command call. (unless %sigchld-handler-installed? (sigaction SIGCHLD handle-SIGCHLD SA_NOCLDSTOP) @@ -916,17 +906,34 @@ its PID." ;; process. (unblock-signals %precious-signals) - (exec-command command - #:user user - #:group group - #:supplementary-groups supplementary-groups - #:log-file log-file - #:directory directory - #:file-creation-mask file-creation-mask - #:create-session? create-session? - #:environment-variables environment-variables)) + (thunk)) pid)))) +(define* (fork+exec-command command + #:key + (user #f) + (group #f) + (supplementary-groups '()) + (log-file #f) + (directory (default-service-directory)) + (file-creation-mask #f) + (create-session? #t) + (environment-variables + (default-environment-variables))) + "Spawn a process that executed COMMAND as per 'exec-command', and return +its PID." + (fork-and-call + (lambda () + (exec-command command + #:user user + #:group group + #:supplementary-groups supplementary-groups + #:log-file log-file + #:directory directory + #:file-creation-mask file-creation-mask + #:create-session? create-session? + #:environment-variables environment-variables)))) + (define* (make-forkexec-constructor command #:key (user #f)