substitute: Ensure backtraces go to file descriptor 4.

Fixes <https://bugs.gnu.org/46362>.
Reported by Zhu Zihao <all_but_last@163.com>.

Previously, backtraces due to uncaught exceptions would always to go
file descriptor 2; the daemon would read it and error out with something
like:

  error: got unexpected path `Backtrace:' from substituter

This patch fixes that by ensuring backtraces are properly displayed on
file descriptor 4.

* guix/scripts/substitute.scm (with-redirected-error-port): New macro.
(guix-substitute): Use 'with-redirected-error-port' instead of 'parameterize'.
This commit is contained in:
Ludovic Courtès 2021-02-24 15:05:06 +01:00
parent e2572aa950
commit ee3226e9d5
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5

View file

@ -896,6 +896,24 @@ (define %error-to-file-descriptor-4?
;; 'guix-daemon' expects. ;; 'guix-daemon' expects.
(make-parameter #t)) (make-parameter #t))
;; The daemon's agent code opens file descriptor 4 for us and this is where
;; stderr should go.
(define-syntax-rule (with-redirected-error-port exp ...)
"Evaluate EXP... with the current error port redirected to file descriptor 4
if needed, as expected by the daemon's agent."
(let ((thunk (lambda () exp ...)))
(if (%error-to-file-descriptor-4?)
(parameterize ((current-error-port (fdopen 4 "wl")))
;; Redirect diagnostics to file descriptor 4 as well.
(guix-warning-port (current-error-port))
;; 'with-continuation-barrier' captures the initial value of
;; 'current-error-port' to report backtraces in case of uncaught
;; exceptions. Without it, backtraces would be printed to FD 2,
;; thereby confusing the daemon.
(with-continuation-barrier thunk))
(thunk))))
(define-command (guix-substitute . args) (define-command (guix-substitute . args)
(category internal) (category internal)
(synopsis "implement the build daemon's substituter protocol") (synopsis "implement the build daemon's substituter protocol")
@ -910,14 +928,7 @@ (define print-build-trace?
(define deduplicate? (define deduplicate?
(find-daemon-option "deduplicate")) (find-daemon-option "deduplicate"))
;; The daemon's agent code opens file descriptor 4 for us and this is where (with-redirected-error-port
;; stderr should go.
(parameterize ((current-error-port (if (%error-to-file-descriptor-4?)
(fdopen 4 "wl")
(current-error-port))))
;; Redirect diagnostics to file descriptor 4 as well.
(guix-warning-port (current-error-port))
(mkdir-p %narinfo-cache-directory) (mkdir-p %narinfo-cache-directory)
(maybe-remove-expired-cache-entries %narinfo-cache-directory (maybe-remove-expired-cache-entries %narinfo-cache-directory
cached-narinfo-files cached-narinfo-files
@ -982,6 +993,7 @@ (define deduplicate?
;;; Local Variables: ;;; Local Variables:
;;; eval: (put 'with-timeout 'scheme-indent-function 1) ;;; eval: (put 'with-timeout 'scheme-indent-function 1)
;;; eval: (put 'with-redirected-error-port 'scheme-indent-function 0)
;;; End: ;;; End:
;;; substitute.scm ends here ;;; substitute.scm ends here