Subject: bug#76698: Activations interfere with each other modules

From: Hilton Chain <[email-masked]>
Date: Thu, 06 Mar 2025 11:13:14 +0800

Hi Tomas,

On Mon, 03 Mar 2025 09:02:22 +0800,
Tomas Volf wrote:
>
> Hello,
>
> when using `activation-service-type' combined with `with-extension', the
> various modules seem to interfere with each other.
>
> In my case the samba-service-type interferes with my custom service:
>
> --8<---------------cut here---------------start------------->8---
> (define (watcher-activation* config)
>   (match-record config <watcher-configuration>
>                 (user group cache-dir state-dir)
>     (with-extension/guile-wolfsden
>      #~(begin
>          (use-modules (wolfsden fs)
>                       (wolfsden sh))
>          (for-each (lambda (dir)
>                      (mkdir-p dir)
>                      (invoke* #$(file-append coreutils "/bin/chown")
>                               "-Rv" (string-append #$user ":" #$group) dir)
>                      (chmod dir #o700))
>                    '(#$cache-dir
>                      #$state-dir))))))
> --8<---------------cut here---------------end--------------->8---
>
> samba-service-type's activation starts with:
>
> --8<---------------cut here---------------start------------->8---
> (define (samba-activation config)
>   (let ((package (samba-configuration-package config))
>         (config-file (samba-configuration-config-file config)))
>     (with-imported-modules '((guix build utils))
> --8<---------------cut here---------------end--------------->8---
>
> Both (guix build utils) and (wolfsden sh) provide (invoke) procedure,
> however with incompatible parameters, leading to somewhat annoying to
> debug issues.  In my case the error was:
>
> --8<---------------cut here---------------start------------->8---
> guix deploy: error: failed to deploy x: failed to switch systems while deploying '127.0.0.1':
> keyword-argument-error #f "Invalid keyword" () ("/etc/samba/smb.conf")
> --8<---------------cut here---------------end--------------->8---
>
> Which makes sense now when I understand what the problem is, but it took
> while to get to it.
>
> I do not think this should be the case.  Either each activation service
> should be isolated into a fresh user module, or the services provided by
> Guix should not introduce any additional modules into the scope.
> Alternatively, each activation service could be wrapped into
> program-file, that would ensure isolation as well.

Activation scripts are already ‘program-file’s, but unfortunately
(gnu build activation) and (guix build utils) are implicit dependencies.  This
is hard to change at the moment.

I have sent a patch which might partially address your issue:

[PATCH v2 3/3] services: activation: Continue on exceptions.
https://issues.guix.gnu.org/73494#26

It executes activation scripts by ‘invoke’, so they won't change the
environment.

What I'm trying to achieve is to avoid blocking the activation process when one
script fails.

With that patch, when one script fails, its backtrace is printed out by
‘invoke’, additionally a warning is emitted to indicate the failed script:
--8<---------------cut here---------------start------------->8---
activating system...
The following derivation will be built:
  /gnu/store/78x8n7b58nqcllfqfpr4p73q6n2wazak-switch-to-system.scm.drv

building /gnu/store/78x8n7b58nqcllfqfpr4p73q6n2wazak-switch-to-system.scm.drv...
making '/var/guix/profiles/system-110-link' the current system...
populating /etc from /gnu/store/v206hfm2idagh2nczc6ii0m628xyg5dk-etc...
setting up privileged programs in '/run/privileged/bin'...
Backtrace:
           3 (primitive-load "/gnu/store/59651880cmil350zf5hagyhdi7y…")
In ice-9/eval.scm:
    619:8  2 (_ #f)
    619:8  1 (_ #(#(#(#(#<directory (guile-user) 7fdc0c317…>) …) …) …))
In unknown file:
           0 (rmdir "/var/run/dbus")

ERROR: In procedure rmdir:
In procedure rmdir: Directory not empty
guix system: warning: failed to activate '/gnu/store/59651880cmil350zf5hagyhdi7y66dgz-activate-service.scm'.
The following derivation will be built:
  /gnu/store/m1c65sxmqvvpfdsazcka51miixcpsy9g-install-bootloader.scm.drv

building /gnu/store/m1c65sxmqvvpfdsazcka51miixcpsy9g-install-bootloader.scm.drv...
guix system: bootloader successfully installed on '(/efi)'
--8<---------------cut here---------------end--------------->8---

(Cc'd Ludo) Any concern on this change?  Does the "TODO: Use 'load-compiled'."
still apply?