unofficial mirror of guix-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Shepherd config file and GEXP semantics
@ 2022-01-30 19:53 Attila Lendvai
  2022-02-05 13:59 ` Ludovic Courtès
  0 siblings, 1 reply; 2+ messages in thread
From: Attila Lendvai @ 2022-01-30 19:53 UTC (permalink / raw)
  To: guix-devel

[-- Attachment #1: Type: text/plain, Size: 2374 bytes --]

dear list,

i'm having a hard time with a service's start GEXP. my service is using a utility module, but when anything is referenced from its toplevel, i get a variable unbound error.

to the best of my knowledge everything is fine with WITH-IMPORTED-MODULES and whatnot. i have digged down into the store to verify the service's generated .scm file.

in fact, if i cut down that file to the relevant parts, then i can even run it using guile -s foo.scm, and it does what i expect.

strangely enough, it also works as i expect it when i run the same code not through a `guix pull` and `guix system reconfigure` on a Guix System, but rather though:

$(./pre-inst-env guix system --no-graphic vm /path/to/swarm.scm)

but now, back to why it probably behaves differently in shepherd: it loads its config file using LOAD-IN-USER-MODULE, which does the following dance:

(define (load-in-user-module file)
  (let ((user-module (make-user-module)))
    (save-module-excursion
     (lambda ()
       (set-current-module user-module)
       (primitive-load file)))))

the service's start procedure is captured and stored as a closure, which is only called *after* the SAVE-MODULE-EXCURSION has been passed.

am i right in assuming that:

1) the global value DEFINE'd on the toplevel of my utility module ends up in this unnamed USER-MODULE's env, and that

2) when the start closure is called, it looks for the global variables in a different global current-module (i probably lack the lingo here), which doesn't have the bindings of my util module, and that's why i get the unbound variable error at service start?

if these assumptions are right, then what is the right way to deal with this? is this something to be fixed in shepherd? as demonstrated by the attached file, there's at least one way to make it work.

to verify this, i have copied some bits from shepherd's code, and attached it in an x.scm file. it exhibits the behavior that an escaping closure doesn't see the variable bindings. but when i eval the closure, then it does work as expected.

you won't be able to run the attached file as-is, but i have added the outputs of the two runs at its end.

any thoughts?

--
• attila lendvai
• PGP: 963F 5D5F 45C7 DFCD 0A39
--
“A slave is one who waits for someone to come and free him.”
	— Ezra Pound (1885–1972)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: x.scm --]
[-- Type: text/x-scheme; name=x.scm, Size: 1917 bytes --]

(define (make-user-module)
  (let ((m (make-fresh-user-module)))
    ;; The typical configuration file wants to do '(make <service> ...)', and
    ;; '(register-services ...)', so provide the relevant bindings by default.
    (module-use! m (resolve-interface '(oop goops)))
    (module-use! m (resolve-interface '(shepherd service)))
    m))

(define (load-in-user-module)
  (let ((user-module (make-user-module)))
    (save-module-excursion
     (lambda ()
       (set-current-module user-module)
       (use-modules (nongnu services swarm-utils))

       ;; this works, i.e. *log-directory* is not unbound upon execution:
       ;; (eval '(lambda ()
       ;;          *log-directory*)
       ;;       user-module)

       (lambda () *log-directory*)
       ))))

(format #t "the result is: ~S~%" ((load-in-user-module)))


$ ./pre-inst-env guix repl -L ../nonguix -- /tmp/x.scm
;;; note: source file ../nonguix/nongnu/services/swarm-utils.scm
;;;       newer than compiled /home/alendvai/.cache/guile/ccache/3.0-LE-8-4.5/home/alendvai/workspace/guix/nonguix/nongnu/services/swarm-utils.scm.go
the result is: #<<parameter> 7f958c58b140 proc: #<procedure 7f958c58fdc0 at ice-9/boot-9.scm:1315:5 () | (x)>>




$ ./pre-inst-env guix repl -L ../nonguix -- /tmp/x.scm
;;; note: source file ../nonguix/nongnu/services/swarm-utils.scm
;;;       newer than compiled /home/alendvai/.cache/guile/ccache/3.0-LE-8-4.5/home/alendvai/workspace/guix/nonguix/nongnu/services/swarm-utils.scm.go
Backtrace:
           4 (primitive-load "/tmp/x.scm")
In ice-9/eval.scm:
   202:51  3 (_ _)
   223:20  2 (proc #(#(#<directory (guix-user) 7fa9fecae6e0>)))
In unknown file:
           1 (%resolve-variable (7 . *log-directory*) #<directory (guix-user) 7fa9fecae6e0>)
In ice-9/boot-9.scm:
  1685:16  0 (raise-exception _ #:continuable? _)

ice-9/boot-9.scm:1685:16: In procedure raise-exception:
error: *log-directory*: unbound variable

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Shepherd config file and GEXP semantics
  2022-01-30 19:53 Shepherd config file and GEXP semantics Attila Lendvai
@ 2022-02-05 13:59 ` Ludovic Courtès
  0 siblings, 0 replies; 2+ messages in thread
From: Ludovic Courtès @ 2022-02-05 13:59 UTC (permalink / raw)
  To: Attila Lendvai; +Cc: guix-devel

Hi,

Attila Lendvai <attila@lendvai.name> skribis:

> (define (make-user-module)
>   (let ((m (make-fresh-user-module)))
>     ;; The typical configuration file wants to do '(make <service> ...)', and
>     ;; '(register-services ...)', so provide the relevant bindings by default.
>     (module-use! m (resolve-interface '(oop goops)))
>     (module-use! m (resolve-interface '(shepherd service)))
>     m))
>
> (define (load-in-user-module)
>   (let ((user-module (make-user-module)))
>     (save-module-excursion
>      (lambda ()
>        (set-current-module user-module)
>        (use-modules (nongnu services swarm-utils))
>
>        ;; this works, i.e. *log-directory* is not unbound upon execution:
>        ;; (eval '(lambda ()
>        ;;          *log-directory*)
>        ;;       user-module)
>
>        (lambda () *log-directory*)
>        ))))

‘use-modules’ is a macro that should only be used at the top level, even
if it sometimes works in different contexts, for now.

Instead, you should use Guile’s first-class module API (info "(guile)
Module System Reflection").  As you noticed in the code you copied from,
you would call ‘module-use!’ and similar procedures.

I don’t see which module ‘*log-directory*’ is in, though.

HTH,
Ludo’.


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-02-05 14:00 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-30 19:53 Shepherd config file and GEXP semantics Attila Lendvai
2022-02-05 13:59 ` Ludovic Courtès

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).