shepherd: (shepherd support) is visible for start GEXP

  • Done
  • quality assurance status badge
Details
2 participants
  • Attila Lendvai
  • Ludovic Courtès
Owner
unassigned
Submitted by
Attila Lendvai
Severity
normal
A
A
Attila Lendvai wrote on 5 Dec 2023 21:10
(name . bug-guix@gnu.org)(address . bug-guix@gnu.org)
TO2FNeuTmzwqAl4Jop72ZUtPv5uZ6dSe7AsRT93F9c3c_GpEebVGl2-DrO49RkUXp6XgyYmNtbK9Or1g97fw0tBGYIE9fHsOCW3UVmE_hjA=@lendvai.name
the facts:
----------

start GEXP's of services are loaded into unnamed modules. the definitions from (shepherd support) are visible in these unnamed modules. see the attached rerpoducer.

it can be run with:

$(guix system --no-graphic vm reproducer.scm)

and in the VM (must use fold, because it's a dumb terminal):

cat /var/log/messages | fold -150

and observe that (shepherd support) is listed.


questions:
----------

is this indended? i.e. part of the shepherd API?

if not, then this is probably a bug. looking at the public definitions in (shepherd support), it's not obvious that those are meant to be available for the users of shepherd. either way, this should probably be documented with at least a comment at the top of the file.

if this is intended, then where is this module imported? i looked all around, and i can't seem to find what mechanism imports this support module into the unnamed module that are used for the GEXPs.


my ultimate issue:
------------------

my service code has conflicting definitions with (shepherd support), and i need to know the intent in the shepherd API to decide on the proper fix.

--
• attila lendvai
• PGP: 963F 5D5F 45C7 DFCD 0A39
--
“Tact is a skill that can turn brutal honesty into just honesty. It's a skill that develops with practice, and one that's harder to use when emotions are running high. But you can't go towards someone with a verbal fist and expect a hug in return. When method matches intention, outcomes are much more peaceful.”
— Doe Zantamata
;; Run with something like this: ;; $(guix system --no-graphic vm reproducer.scm) (define-module (reproducer) #:use-module (gnu system) #:use-module (gnu system shadow) #:use-module (gnu system nss) #:use-module (gnu system vm) #:use-module (gnu tests) #:use-module (gnu services) #:use-module (gnu services base) #:use-module (gnu services dbus) #:use-module (gnu services shepherd) #:use-module (gnu packages admin) #:use-module (gnu packages base) #:use-module (gnu packages bash) #:use-module (gnu packages certs) #:use-module (gnu packages package-management) #:use-module (gnu packages linux) #:use-module (guix gexp) #:use-module (guix git) #:use-module (guix git-download) #:use-module (guix store) #:use-module (guix modules) #:use-module (guix packages) #:use-module (srfi srfi-1) #:use-module (ice-9 match)) (operating-system (inherit %simple-os) (services (cons* (simple-service 'reproducer shepherd-root-service-type (list (shepherd-service (requirement '(file-systems)) (provision '(reproducer)) (documentation "") (start #~(begin (lambda _ (format #t "*** reproducer gexp speaking, \ current module: ~A, \ module-uses: ~A, \ ringbuffer: ~A~%" (current-module) (module-uses (current-module)) (and=> (module-variable (current-module) 'ring-buffer) variable-ref)) 0)))))) %base-services)))
L
L
Ludovic Courtès wrote on 21 Mar 15:56 +0100
(name . Attila Lendvai)(address . attila@lendvai.name)(address . 67649@debbugs.gnu.org)
871q83vdkc.fsf@gnu.org
Hi,

Attila Lendvai <attila@lendvai.name> skribis:

Toggle quote (2 lines)
> start GEXP's of services are loaded into unnamed modules. the definitions from (shepherd support) are visible in these unnamed modules. see the attached rerpoducer.

It’s more than (shepherd support):

Toggle snippet (26 lines)
shepherd[1]: Starting service reproducer...
shepherd[1]: *** reproducer gexp speaking, current module: #<module (#{ g107}#) 7f2cf85a1be0>, mor
face (oop goops) 7f2cf8a89c80> #<interface (shepherd service) 7f2cf8526780> #<interface (srfi srf)
7f2cf8a898c0> #<interface (system repl error-handling) 7f2cf85a18c0> #<custom-interface (guix buc
alls) 7f2cf7ac2be0> #<custom-interface (guix build utils) 7f2cf7ac2280> #<custom-interface (gnu b
file-systems) 7f2cf7b671e0> #<interface (gnu system file-systems) 7f2cf7b258c0> #<custom-interface
(gnu build file-systems) 7f2cf7b670a0> #<custom-interface (guix build utils) 7f2cf7b67000> #<cusi
nterface (gnu build file-systems) 7f2cf7b8ef00> #<custom-interface (guix build utils) 7f2cf7b8ee67
b8edc0> #<custom-interface (guix build utils) 7f2cf7b8ed20> #<custom-interface (guix build utils)c
f7b8ec80> #<custom-interface (guix build utils) 7f2cf7b8ebe0> #<custom-interface (guix build util7
f2cf7b8e8c0> #<interface (gnu system accounts) 7f2cf7b8e640> #<custom-interface (guix build utils2
cf8606d20> #<custom-interface (guix build utils) 7f2cf8606c80> #<interface (gnu build linux-boot)
7f2cf8606be0> #<interface (ice-9 popen) 7f2cf8606960> #<interface (ice-9 rdelim) 7f2cf8a42f00> #<r

608c0> #<custom-interface (guix build utils) 7f2cf7adfe60> #<custom-interface (guix build utils) 7
f2cf7adfd20> #<custom-interface (guix build utils) 7f2cf7adfc80> #<custom-interface (guix build u)
7f2cf7adfbe0> #<custom-interface (guix build utils) 7f2cf7adfb40> #<custom-interface (guix build
utils) 7f2cf7adfa00> #<custom-interface (guix build utils) 7f2cf7adf960> #<custom-interface (guixl
d utils) 7f2cf7adf8c0> #<custom-interface (guix build utils) 7f2cf7adf820> #<custom-interface (gui
x build utils) 7f2cf7adf6e0> #<custom-interface (guix build utils) 7f2cf7adf640> #<custom-interfag
uix build utils) 7f2cf7adf5a0> #<custom-interface (guix build utils) 7f2cf7adf500> #<custom-interr
fi srfi-26) 7f2cf8e83f00> #<custom-interface (shepherd support) 7f2cf7adf3c0> #<custom-interface x
build utils) 7f2cf7adf320> #<interface (ip addr) 7f2cf7adf000> #<interface (ip link) 7f2cf7f3ed2(
ice-9 format) 7f2cf9fed6e0>), ringbuffer: #<procedure ring-buffer (size)>

Toggle quote (2 lines)
> is this indended? i.e. part of the shepherd API?

It’s not really intended.

In Guix, ‘shepherd-service’ instances have a ‘modules’ field. Many,
like the one for mcron, have (shepherd support) there because they need
it for one thing or another.

Now, your ‘reproducer’ service has a default ‘modules’ field so why does
it see those modules anyway?

First, note that (current-module) called from the ‘start’ method does
*not* return the module where that ‘start’ method was defined.

Still, what we see here is that the module in which the shepherd config
file is evaluated has way more imports than expected. This stems from
the way services get loaded on Guix System, in
‘shepherd-configuration-file’:

(register-services
(parameterize ((current-warning-port
(%make-void-port "w")))
(map load-compiled '#$(map scm->go files))))

Thus, each one of ‘files’ augments the imports of the current module,
eventually leading to this import soup.

This is a Guix bug we can fix by loading each service file in a fresh
module:
Toggle diff (33 lines)
diff --git a/gnu/services/shepherd.scm b/gnu/services/shepherd.scm
index f5bcde721f..6b8527f0dc 100644
--- a/gnu/services/shepherd.scm
+++ b/gnu/services/shepherd.scm
@@ -383,6 +383,14 @@ (define (shepherd-configuration-file services shepherd)
(use-modules (srfi srfi-34)
(system repl error-handling))
+ (define (make-user-module)
+ ;; Copied from (shepherd support), where it's private.
+ (let ((m (make-fresh-user-module)))
+ ;; The typical configuration file wants to do '(service ...)', and
+ ;; '(register-services ...)', so provide the relevant bindings by default.
+ (module-use! m (resolve-interface '(shepherd service)))
+ m))
+
;; There's code run from shepherd that uses 'call-with-input-file' &
;; co.--e.g., the 'urandom-seed' service. Starting from Shepherd
;; 0.9.2, users need to make sure not to leak non-close-on-exec file
@@ -416,7 +424,12 @@ (define (shepherd-configuration-file services shepherd)
(register-services
(parameterize ((current-warning-port
(%make-void-port "w")))
- (map load-compiled '#$(map scm->go files))))))
+ (map (lambda (file)
+ (save-module-excursion
+ (lambda ()
+ (set-current-module (make-user-module))
+ (load-compiled file))))
+ '#$(map scm->go files))))))
(format #t "starting services...~%")
(let ((services-to-start
There might be breakage due to services that currently get the modules
they need “by chance” (as a side effect of loading another module), but
at least this small sample works fine:

make check-system TESTS="basic openssh nginx static-networking static-networking-advanced mcron hpcguix-web" -j4

I’ll push the patch soonish.

Thanks!

Ludo’.
L
L
Ludovic Courtès wrote on 31 Mar 16:20 +0200
(name . Attila Lendvai)(address . attila@lendvai.name)(address . 67649-done@debbugs.gnu.org)
87ttkmeb4g.fsf@gnu.org
Hi,

Ludovic Courtès <ludo@gnu.org> skribis:

Toggle quote (3 lines)
> This is a Guix bug we can fix by loading each service file in a fresh
> module:

[...]

Toggle quote (2 lines)
> I’ll push the patch soonish.

Pushed as 6f9d844d2ece7b369d17bbe678978462425f869c last week.

Thanks!

Ludo’.
Closed
?
Your comment

This issue is archived.

To comment on this conversation send an email to 67649@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 67649
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch