[bug#73494,v4,1/3] services: activation: Continue on exceptions.
Commit Message
From: Hilton Chain <hako@ultrarare.space>
Use ‘invoke’ for backtraces and avoid changing environment.
* gnu/services.scm (activation-script): Execute activation scripts in
‘invoke’.
Warn about failed activation scripts.
Change-Id: I89be31433fbb46d0c4a9dc6115ab167910840b6f
Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
---
gnu/services.scm | 32 +++++++++++++++++++++++++++-----
1 file changed, 27 insertions(+), 5 deletions(-)
base-commit: 2b4680c6c17bd6470f78a1f39d2f7af8b05e279f
Comments
On Tue, 29 Apr 2025 15:17:43 +0800,
Maxim Cournoyer wrote:
>
> From: Hilton Chain <hako@ultrarare.space>
>
> Use ‘invoke’ for backtraces and avoid changing environment.
>
> * gnu/services.scm (activation-script): Execute activation scripts in
> ‘invoke’.
> Warn about failed activation scripts.
>
> Change-Id: I89be31433fbb46d0c4a9dc6115ab167910840b6f
> Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
> ---
> gnu/services.scm | 32 +++++++++++++++++++++++++++-----
> 1 file changed, 27 insertions(+), 5 deletions(-)
I think this patch needs updating for 76698. Will take a look later.
Hello,
Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:
> From: Hilton Chain <hako@ultrarare.space>
>
> Use ‘invoke’ for backtraces and avoid changing environment.
>
> * gnu/services.scm (activation-script): Execute activation scripts in
> ‘invoke’.
> Warn about failed activation scripts.
>
> Change-Id: I89be31433fbb46d0c4a9dc6115ab167910840b6f
> Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
[...]
> ;; Run the services' activation snippets.
> - ;; TODO: Use 'load-compiled'.
> - (for-each primitive-load '#$actions)))))
> + (for-each (lambda (action)
> + ;; Don't block activation process when one
> + ;; action fails.
> + (catch #t
> + (lambda ()
> + (invoke action))
> + (lambda _
> + (warning
> + (G_ "failed to activate '~a'.~%")
> + action))))
> + '#$actions)))))
As I suggested upthread (or elsewhere? I’m lost!), I think it would be
enough to keep loading these files in the main process (as opposed to
spawning one short-lived process for each activation) and simply catch
exceptions:
(for-each (lambda (file)
(guard (c …)
(save-module-excursion
…)))
'#$actions)
I think it would do what we want while avoiding the overhead. I don’t
think it qualifies as “premature optimization” because it’s already in
place and the semantics are well-defined.
Thoughts?
Ludo’.
On Sat, 03 May 2025 00:17:23 +0800,
Ludovic Courtès wrote:
>
> Hello,
>
> Maxim Cournoyer <maxim.cournoyer@gmail.com> writes:
>
> > From: Hilton Chain <hako@ultrarare.space>
> >
> > Use ‘invoke’ for backtraces and avoid changing environment.
> >
> > * gnu/services.scm (activation-script): Execute activation scripts in
> > ‘invoke’.
> > Warn about failed activation scripts.
> >
> > Change-Id: I89be31433fbb46d0c4a9dc6115ab167910840b6f
> > Signed-off-by: Maxim Cournoyer <maxim.cournoyer@gmail.com>
>
> [...]
>
> > ;; Run the services' activation snippets.
> > - ;; TODO: Use 'load-compiled'.
> > - (for-each primitive-load '#$actions)))))
> > + (for-each (lambda (action)
> > + ;; Don't block activation process when one
> > + ;; action fails.
> > + (catch #t
> > + (lambda ()
> > + (invoke action))
> > + (lambda _
> > + (warning
> > + (G_ "failed to activate '~a'.~%")
> > + action))))
> > + '#$actions)))))
>
> As I suggested upthread (or elsewhere? I’m lost!), I think it would be
> enough to keep loading these files in the main process (as opposed to
> spawning one short-lived process for each activation) and simply catch
> exceptions:
>
> (for-each (lambda (file)
> (guard (c …)
> (save-module-excursion
> …)))
> '#$actions)
>
> I think it would do what we want while avoiding the overhead. I don’t
> think it qualifies as “premature optimization” because it’s already in
> place and the semantics are well-defined.
Implemented in v6.
@@ -692,15 +692,28 @@ (define* (activation-service->script service)
(define (activation-script gexps)
"Return the system's activation script, which evaluates GEXPS."
(define actions
- (map (cut program-file "activate-service.scm" <>) gexps))
+ (map (lambda (action)
+ (program-file "activate-service.scm"
+ (with-imported-modules (source-module-closure
+ '((gnu build activation)
+ (guix build utils)))
+ #~(begin
+ (use-modules (gnu build activation)
+ (guix build utils))
+ #$action))))
+ gexps))
(program-file "activate.scm"
(with-imported-modules (source-module-closure
'((gnu build activation)
- (guix build utils)))
+ (guix build utils)
+ (guix diagnostics)
+ (guix i18n)))
#~(begin
(use-modules (gnu build activation)
- (guix build utils))
+ (guix build utils)
+ (guix diagnostics)
+ (guix i18n))
(mkdir-p "/var/run")
;; Make sure the user accounting database exists. If it
@@ -719,8 +732,17 @@ (define (activation-script gexps)
(activate-current-system)
;; Run the services' activation snippets.
- ;; TODO: Use 'load-compiled'.
- (for-each primitive-load '#$actions)))))
+ (for-each (lambda (action)
+ ;; Don't block activation process when one
+ ;; action fails.
+ (catch #t
+ (lambda ()
+ (invoke action))
+ (lambda _
+ (warning
+ (G_ "failed to activate '~a'.~%")
+ action))))
+ '#$actions)))))
(define (gexps->activation-gexp gexps)
"Return a gexp that runs the activation script containing GEXPS."