Subject: Re: bug#41028: Channel/inferior error with core-updates: Unbound variable: call-with-new-thread

From: Ludovic Courtès <[email-masked]>
Date: Tue, 05 May 2020 23:24:22 +0200

Hey!

Christopher Baines <[email-masked]> skribis:

> → guix build -f test.scm 
> Updating channel 'guix' from Git repository at 'https://git.savannah.gnu.org/git/guix.git'...
> Backtrace:
>            4 (primitive-load "/gnu/store/8mv5bpjgxg9c369xnbb5rf1kv9r?")
> In ice-9/eval.scm:
>     619:8  3 (_ #(#(#(#(#(#(#(#(#(#(#(?) ?) ?) ?) ?) ?) ?) ?) ?) ?) ?))
>    182:19  2 (proc #(#(#(#(#(#(#(#(#(#(# ?) ?) ?) ?) ?) ?) ?) ?) ?) ?))
>    142:16  1 (compile-top-call #<directory (guile-user) 7f1e0abc1f00> ?)
> In unknown file:
>            0 (%resolve-variable (7 . call-with-new-thread) #<directo?>)
>
> ERROR: In procedure %resolve-variable:
> Unbound variable: call-with-new-thread
> guix build: error: You found a bug: the program '/gnu/store/8mv5bpjgxg9c369xnbb5rf1kv9r6z5hw-compute-guix-derivation'
> failed to compute the derivation for Guix (version: "e02c2f85b36ce1c733bd908a210ce1182bdd2560"; system: "x86_64-linux";
> host version: "a8cb1e72ef351330d1521833c1b270dcc0da593f"; pull-version: 1).

A summary of the IRC discussion and experiments:

  1. The underlying problem is a missing (ice-9 threads) import in the
     ‘compute-guix-derivation’ script, fixed in
     05e783871c2c69b402e088863d46f5be7915ac74.

  2. The ‘%quirks’ mechanism in (guix channels) doesn’t work as is here
     because what we would need to change is the #:guile parameter
     passed to ‘gexp->script’ (the one defined in build-self.scm).
     Attached a patch to add a quirk but that doesn’t solve the problem.

Possible solutions include:

  a. Changing the value returned by ‘default-guile’ as used by
     ‘gexp->script’.

  b. Supporting the definition of quirks that patch the code.

Thanks,
Ludo’.

diff --git a/guix/channels.scm b/guix/channels.scm
index 041fae2a9c..cbb0a97546 100644
--- a/guix/channels.scm
+++ b/guix/channels.scm
@@ -328,16 +328,34 @@ to '%package-module-path'."
           #f
           (apply throw args)))))
 
+(define (missing-ice-9-threads-import? source)
+  "Return true of %SELF-BUILD-FILE is missing an (ice-9 threads) import as
+described at <https://bugs.gnu.org/41028>."
+  (define content
+    (call-with-input-file (string-append source "/" %self-build-file)
+      read-string))
+
+  ;; The faulty code uses 'call-with-new-thread' without importing (ice-9
+  ;; threads).  However, the 'call-with-new-thread' binding is no longer
+  ;; available in the default name space on Guile 3.0.
+  (and (string-contains content "(call-with-new-thread")
+       (not (string-contains content "(ice-9 threads)"))))
+
 (define (guile-2.2.4)
   (module-ref (resolve-interface '(gnu packages guile))
               'guile-2.2.4))
 
+(define (guile-2.2)
+  (module-ref (resolve-interface '(gnu packages guile))
+              'guile-2.2))
+
 (define %quirks
   ;; List of predicate/package pairs.  This allows us provide information
   ;; about specific Guile versions that old Guix revisions might need to use
   ;; just to be able to build and run the trampoline in %SELF-BUILD-FILE.  See
   ;; <https://bugs.gnu.org/37506>
-  `((,syscalls-reexports-local-variables? . ,guile-2.2.4)))
+  `((,syscalls-reexports-local-variables? . ,guile-2.2.4)
+    (,missing-ice-9-threads-import? . ,guile-2.2)))
 
 (define* (guile-for-source source #:optional (quirks %quirks))
   "Return the Guile package to use when building SOURCE or #f if the default
@@ -372,32 +390,32 @@ package modules under SOURCE using CORE, an instance of Guix."
     (string-append source "/" %self-build-file))
 
   (if (file-exists? script)
-      (let ((build (save-module-excursion
-                    (lambda ()
-                      ;; Disable deprecation warnings; it's OK for SCRIPT to
-                      ;; use deprecated APIs and the user doesn't have to know
-                      ;; about it.
-                      (parameterize ((guix-warning-port
-                                      (%make-void-port "w")))
-                        (primitive-load script)))))
-            (guile (guile-for-source source)))
+      (mlet* %store-monad ((guile -> (guile-for-source source))
+                           (_        (mwhen guile
+                                       (set-guile-for-build (pk 'G guile))))
+                           (build -> (save-module-excursion
+                                      (lambda ()
+                                        ;; Disable deprecation warnings; it's
+                                        ;; OK for SCRIPT to use deprecated
+                                        ;; APIs and the user doesn't have to
+                                        ;; know about it.
+                                        (parameterize ((guix-warning-port
+                                                        (%make-void-port "w")))
+                                          (primitive-load script))))))
         ;; BUILD must be a monadic procedure of at least one argument: the
         ;; source tree.
         ;;
         ;; Note: BUILD can return #f if it does not support %PULL-VERSION.  In
         ;; the future we'll fall back to a previous version of the protocol
         ;; when that happens.
-        (mbegin %store-monad
-          (mwhen guile
-            (set-guile-for-build guile))
 
-          ;; BUILD is usually quite costly.  Install a "trivial" build handler
-          ;; so we don't bounce an outer build-accumulator handler that could
-          ;; cause us to redo half of the BUILD computation several times just
-          ;; to realize it gives the same result.
-          (with-trivial-build-handler
-           (build source #:verbose? verbose? #:version commit
-                  #:pull-version %pull-version))))
+        ;; BUILD is usually quite costly.  Install a "trivial" build handler
+        ;; so we don't bounce an outer build-accumulator handler that could
+        ;; cause us to redo half of the BUILD computation several times just
+        ;; to realize it gives the same result.
+        (with-trivial-build-handler
+         (build source #:verbose? verbose? #:version commit
+                #:pull-version %pull-version)))
 
       ;; Build a set of modules that extend Guix using the standard method.
       (standard-module-derivation name source core dependencies)))