From unknown Fri Jun 20 05:37:16 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#75595 <75595@debbugs.gnu.org> To: bug#75595 <75595@debbugs.gnu.org> Subject: Status: [PATCH 0/4] 'guix container run' and isolated inferiors Reply-To: bug#75595 <75595@debbugs.gnu.org> Date: Fri, 20 Jun 2025 12:37:16 +0000 retitle 75595 [PATCH 0/4] 'guix container run' and isolated inferiors reassign 75595 guix-patches submitter 75595 Ludovic Court=C3=A8s severity 75595 normal tag 75595 patch thanks From debbugs-submit-bounces@debbugs.gnu.org Wed Jan 15 17:13:59 2025 Received: (at submit) by debbugs.gnu.org; 15 Jan 2025 22:14:00 +0000 Received: from localhost ([127.0.0.1]:59057 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tYBeB-0002iw-Dl for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:13:59 -0500 Received: from lists.gnu.org ([2001:470:142::17]:50804) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tYBe8-0002ig-Mb for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:13:57 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBe1-0002t7-8G for guix-patches@gnu.org; Wed, 15 Jan 2025 17:13:50 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBdz-0003y7-Jx; Wed, 15 Jan 2025 17:13:47 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:Date:Subject:To:From:in-reply-to: references; bh=WRcyM518rUoL3+zUi4386KTCY6HotShgqOqtO1X6xKA=; b=HI8PeRXVn6NlWZ ogwNRfPv+VPyAEx0+Qu5IJjReLTtW3/2fHqk55gOV2oe4OnWje+ot+Cw2Oqs4bccld8SNzUsk42lm paz5qOx25k1cofR1NmiP5W76R7mfodU/q0Yntx1mfFM03JaBR78I53MvpQVSiiTC+DWidop+dSkig z6NaLogdTtgdqkQkkXS+G2WiiuelBT2IakNJgZv7M4OZB4xf4zrGly5zOaQztVAM5RUupVmlzRy/d 1fBkJtN4sqPVU63tHXoxWyjtj/A7cLz/M7cS6yMjEY4eEw9/qVtbkql2rXh10v4GTjHdYSccz/2ew xc5mcXer7fd4QeXxbGyg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= To: guix-patches@gnu.org Subject: [PATCH 0/4] 'guix container run' and isolated inferiors Date: Wed, 15 Jan 2025 23:13:38 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines , Josselin Poiret , Ludovic Courtès , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice Content-Transfer-Encoding: 8bit X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: submit Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= , Christopher Baines , Josselin Poiret X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Hello! You might remember that back in 2018, I sent a ‘guix run’ command that would let you run programs in a container with hopefully exactly the authority it needs: https://lists.gnu.org/archive/html/help-guix/2018-01/msg00108.html This patch series adds an improved version of that command as ‘guix container run’. By default, it figures out what extra authority to give: for X11 programs, it lets ‘DISPLAY’ through and bind-mounts /tmp/.X11-unix, for DBus programs it maps /etc/machine-id, and so on. Alternatively, you can use ‘--bare’ and you get a bare container in the style of ‘guix shell -C’. It supports ‘-N’, ‘--expose’, and other options found in ‘guix shell -C’ and related commands. ~~~ But really, my initial motivation was to run inferiors in a container. Christopher implemented that years ago, using (gnu build linux-container): https://issues.guix.gnu.org/34638 There were small issues that needed to be addressed, but the main problem I would have with it today is the fact that we’d call ‘clone’ directly, making it effectively unusuable in a multi-threaded context (see horror story in , which led to the implementation of ‘spawn’ in Guile by Josselin.) So I thought that by having a command-line interface to ‘call-with-container’ (!), which is essentially what ‘guix container run’ is, we would be able to use ‘posix_spawn’ to run that CLI and spawn inferiors without risk. Incidentally, it is rather simple to implement and reason about. This is what the last patch does. I didn’t add tests: the ‘guix’ binary needs to be in the store, which makes it hard to test. But here’s an example session: --8<---------------cut here---------------start------------->8--- $ ./pre-inst-env guile -q GNU Guile 3.0.9 Copyright (C) 1995-2023 Free Software Foundation, Inc. Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. This program is free software, and you are welcome to redistribute it under certain conditions; type `,show c' for details. Enter `,help' for help. scheme@(guile-user)> ,use(guix inferior) scheme@(guile-user)> (open-inferior "/home/ludo/.config/guix/current" #:isolated? #t) $1 = # scheme@(guile-user)> (inferior-eval '(use-modules (ice-9 ftw)) $1) $2 = #> scheme@(guile-user)> (inferior-eval '(scandir "/home/ludo") $1) $3 = ("." ".." ".cache") scheme@(guile-user)> ,use(guix) scheme@(guile-user)> (define s (open-connection)) scheme@(guile-user)> (inferior-eval-with-store $1 s `(lambda (s) (add-text-to-store s "isolated" "hi from inferior!"))) $4 = "/gnu/store/kvnxfbcwn5sdr02y75v2w4fswns0ql8d-isolated" --8<---------------cut here---------------end--------------->8--- Thoughts? Ludo’. Ludovic Courtès (4): DRAFT container: Add ‘run’ sub-command. tests: Make ‘inferior-eval-with-store’ test more robust. inferior: Store the bridge directory name in . inferior: Allow running inferiors in a container. Makefile.am | 3 +- guix/inferior.scm | 184 ++++++++++++++------ guix/scripts/container.scm | 4 +- guix/scripts/container/run.scm | 301 +++++++++++++++++++++++++++++++++ tests/inferior.scm | 19 ++- 5 files changed, 446 insertions(+), 65 deletions(-) create mode 100644 guix/scripts/container/run.scm base-commit: d804997897d2a531e0e3186e64df798a7e2e0d1a -- 2.47.1 From debbugs-submit-bounces@debbugs.gnu.org Wed Jan 15 17:15:07 2025 Received: (at 75595) by debbugs.gnu.org; 15 Jan 2025 22:15:07 +0000 Received: from localhost ([127.0.0.1]:59072 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tYBfG-0002pR-4O for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60064) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tYBfD-0002lB-Nm for 75595@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:04 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBf8-00041w-EE; Wed, 15 Jan 2025 17:14:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=13u6fOIDbADLF4w9/BD9fWokUtcwkgJVmoylI1L/8Do=; b=Mo1SVjOaS1G2WEj1KVwc skibGYrMuU6joTHFCRGUkqd5sNzVMlixb9NJouMduu/NgyDeLXllF/Ik7Y3pJSsKw7ipDKytiWKuX oKMvvjNE9tticytHqr3bzzSNslxTQD2XRAyf9Lrp40ER0VxMvtVCEB2PeJn/mrf/hOLbHbtCqxVQQ 0oW/Vnk6cu+jwVuizLqhQtBX6kvdWmgzLFnFave3XufNSpiFyCNZjqql8EbWB3lOhLGK5VUtmx8si OZsYvvo3cttN1GFia0jgAyqC+JqwGSPB5MT6E2xvMHK2vPgY9uDP1ImWXFv1X3bSabYjvAUeYxF2C 5RZcZBOgIavBxg==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= To: 75595@debbugs.gnu.org Subject: [PATCH 1/4] =?UTF-8?q?DRAFT=20container:=20Add=20=E2=80=98run?= =?UTF-8?q?=E2=80=99=20sub-command.?= Date: Wed, 15 Jan 2025 23:14:47 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines , Josselin Poiret , Ludovic Courtès , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75595 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) DRAFT missing doc and tests. * guix/scripts/container.scm (show-help, %actions): Add “run”. * guix/scripts/container/run.scm: New file. * Makefile.am (MODULES): Add it. Change-Id: I0ca1d085649ac059aab597f48bea6e480004bf4c --- Makefile.am | 3 +- guix/scripts/container.scm | 4 +- guix/scripts/container/run.scm | 301 +++++++++++++++++++++++++++++++++ 3 files changed, 306 insertions(+), 2 deletions(-) create mode 100644 guix/scripts/container/run.scm diff --git a/Makefile.am b/Makefile.am index f911d432dd..6a3c14278a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,5 +1,5 @@ # GNU Guix --- Functional package management for GNU -# Copyright © 2012-2024 Ludovic Courtès +# Copyright © 2012-2025 Ludovic Courtès # Copyright © 2013 Andreas Enge # Copyright © 2015, 2017 Alex Kost # Copyright © 2016, 2018 Mathieu Lirzin @@ -380,6 +380,7 @@ MODULES = \ guix/scripts/weather.scm \ guix/scripts/container.scm \ guix/scripts/container/exec.scm \ + guix/scripts/container/run.scm \ guix/scripts/deploy.scm \ guix/scripts/time-machine.scm \ guix.scm \ diff --git a/guix/scripts/container.scm b/guix/scripts/container.scm index 70637bca29..becc096744 100644 --- a/guix/scripts/container.scm +++ b/guix/scripts/container.scm @@ -31,6 +31,8 @@ (define (show-help) (newline) (display (G_ "\ exec execute a command inside of an existing container\n")) + (display (G_ "\ + run run the given command in a new container\n")) (newline) (display (G_ " -h, --help display this help and exit")) @@ -39,7 +41,7 @@ (define (show-help) (newline) (show-bug-report-information)) -(define %actions '("exec")) +(define %actions '("exec" "run")) (define (resolve-action name) (let ((module (resolve-interface diff --git a/guix/scripts/container/run.scm b/guix/scripts/container/run.scm new file mode 100644 index 0000000000..fd4e8a5547 --- /dev/null +++ b/guix/scripts/container/run.scm @@ -0,0 +1,301 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2018-2020, 2025 Ludovic Courtès +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (guix scripts container run) + #:use-module (guix ui) + #:use-module (guix utils) + #:use-module (guix scripts) + #:use-module (guix store) + #:use-module (guix packages) + #:use-module (guix derivations) + #:use-module ((guix build utils) #:select (which mkdir-p)) + #:use-module (gnu build linux-container) + #:use-module (gnu system file-systems) + #:use-module (gnu packages) + #:use-module (srfi srfi-1) + #:use-module (srfi srfi-9 gnu) + #:use-module (srfi srfi-26) + #:use-module (srfi srfi-37) + #:use-module (srfi srfi-71) + #:use-module (ice-9 match) + #:export (guix-container-run)) + + +;;; +;;; Strongbox. +;;; + +(define (bind-mount-spec/ro item) + (and (file-exists? item) + (file-system + (device item) + (mount-point item) + (type "none") + (flags '(bind-mount read-only)) + (check? #f)))) + +(define (bind-mount-spec/rw item) + (and (file-exists? item) + (file-system + (inherit (bind-mount-spec/ro item)) + (flags '(bind-mount))))) + +;; Safe in which applications run. +(define-immutable-record-type + (safe namespaces mappings environment) + safe? + (namespaces safe-namespaces) + (mappings safe-mappings) + (environment safe-environment-variables)) + +(define (store-item-features store items) + "Return a list of \"features\" for ITEM, where features are symbols such as +'x11, 'dbus, 'alsa, etc. The feature list is determined as a function of the +packages presumably among ITEMS." + (define packages + (map (compose (cut package-name->name+version <> #\-) + store-path-package-name) + items)) + + (letrec-syntax ((features (syntax-rules (->) + ((_ (package -> feature) rest ...) + (let ((lst (features rest ...))) + (if (member package packages) + (cons 'feature lst) + lst))) + ((_) + '())))) + (features ("libx11" -> x11) + ("dbus" -> dbus) + ("alsa-lib" -> alsa) + ("pulseaudio" -> pulseaudio) + ("guix" -> guix)))) + +(define (features->safe features) + "Return a safe for the given FEATURES, a list of symbols." + (define x11? (memq 'x11 features)) + (define network? (memq 'network features)) + (define dbus? (memq 'dbus features)) + (define alsa? (memq 'alsa features)) + (define pulseaudio? (memq 'pulseaudio features)) + (define guix? (memq 'guix features)) + + (define mappings + (let-syntax ((if (syntax-rules () + ((_ condition body) + (if condition + (or (and=> body list) '()) + '())))) + (ro (identifier-syntax bind-mount-spec/ro)) + (rw (identifier-syntax bind-mount-spec/rw))) + `(,@(if network? (ro "/var/run/nscd/socket")) + ,@(if network? (ro "/etc/ssl")) + ,@(if (and guix? (string-prefix? "/" (%daemon-socket-uri))) + (ro (%daemon-socket-uri))) + ,@(if (or guix? network?) ;/etc/ssl/certs/* points to the store + (ro (%store-prefix))) ;the entire store + ,@(if guix? + (rw (string-append (getenv "HOME") "/.cache/guix"))) + ,@(if x11? (rw (string-append (getenv "HOME") "/.Xauthority"))) + ,@(if x11? (rw "/tmp/.X11-unix")) + ,@(if x11? (rw (string-append "/run/user/" + (number->string (getuid))))) + ,@(if dbus? (ro "/etc/machine-id")) + ,@(if alsa? (rw "/dev/snd")) + ,@(if pulseaudio? (rw (string-append (getenv "HOME") "/.pulse")))))) + + (define namespaces + ;; X11 applications need to run in the same IPC namespace as + ;; the server. + (let ((withdrawn `(,@(if x11? '(ipc) '()) + ,@(if network? '(net) '())))) + (fold delq %namespaces withdrawn))) + + (define environment-variables + `("HOME" + ,@(if x11? '("DISPLAY") '()) + ,@(if (or dbus? x11?) '("XDG_RUNTIME_DIR") '()))) + + (safe namespaces mappings environment-variables)) + +(define (store-mapping? file-system) + "Return true if FILE-SYSTEM mounts the store." + (string=? (file-system-mount-point file-system) + (%store-prefix))) + + +;;; +;;; Options. +;;; + +(define %options + (list (option '("bare") #f #f + (lambda (opt name arg result) + (alist-cons 'bare? #t result))) + (option '(#\N "network") #f #f + (lambda (opt name arg result) + (alist-cons 'feature 'network result))) + (option '(#\W "nesting") #f #f + (lambda (opt name arg result) + (alist-cons 'feature 'guix result))) + (option '(#\g "feature") #t #f + (lambda (opt name arg result) + (alist-cons 'feature (string->symbol arg) result))) + (option '("no-cwd") #f #f + (lambda (opt name arg result) + (alist-cons 'no-cwd? #t result))) + (option '("share") #t #f + (lambda (opt name arg result) + (alist-cons 'file-system-mapping + (specification->file-system-mapping arg #t) + result))) + (option '("expose") #t #f + (lambda (opt name arg result) + (alist-cons 'file-system-mapping + (specification->file-system-mapping arg #f) + result))) + + (option '(#\h "help") #f #f + (lambda args + (show-help) + (exit 0))) + (option '(#\V "version") #f #f + (lambda args + (show-version-and-exit "guix run"))))) + +(define (show-help) + (display (G_ "Usage: guix run COMMAND... +Run COMMAND from PACKAGE in a container.\n")) + (display (G_ " + --bare create a bare environment without attempting + to guess the features needed by COMMAND")) + (display (G_ " + -N, --network provide access the network")) + (display (G_ " + -W, --nesting allow use of Guix within the container")) + (display (G_ " + -g, --feature=NAME provide access to feature NAME")) + (display (G_ " + --no-cwd do not share current working directory with an + isolated container")) + + (display (G_ " + --share=SPEC share writable host file system according to SPEC")) + (display (G_ " + --expose=SPEC expose read-only host file system according to SPEC")) + (newline) + (display (G_ " + -h, --help display this help and exit")) + (display (G_ " + -V, --version display version information and exit")) + (newline) + (show-bug-report-information)) + + +;;; +;;; Entry point. +;;; + +(define (guix-container-run . args) + (define (parse-options) + (args-fold* args %options + (lambda (opt name arg result) + (leave (G_ "~A: unrecognized option~%") name)) + (lambda (arg result) + (alist-cons 'argument arg result)) + '())) + + (define %not-colon + (char-set-complement (char-set #\:))) + + (with-error-handling + (let ((options (parse-options))) + (match (reverse (filter-map (match-lambda + (('argument . argument) argument) + (_ #f)) + options)) + ((command args ...) + (with-store store + (let* ((full (search-path (string-tokenize (getenv "PATH") + %not-colon) + command)) + (resolved (and=> full readlink*)) + (prefix (and=> resolved (lambda (file) + (and (store-path? file) + (direct-store-path file)))))) + (unless full + (leave (G_ "command '~a' not found~%") command)) + (unless prefix + (leave (G_ "command '~a' is not in '~a'~%") + command (%store-prefix))) + + (let* ((items (requisites store (list prefix))) + (features (append (filter-map (match-lambda + (('feature . feature) + feature) + (_ #f)) + options) + (if (assoc-ref options 'bare?) + '() + (store-item-features store items)))) + (safe (features->safe features)) + (cwd (getcwd)) + (environment + (filter-map (lambda (variable) + (match (getenv variable) + (#f #f) + (value (string-append variable "=" + value)))) + (safe-environment-variables safe))) + (mappings + (append (safe-mappings safe) + (if (find store-mapping? (safe-mappings safe)) + '() ;the whole store is mapped + (map bind-mount-spec/ro items)) + (filter-map (match-lambda + (('file-system-mapping . mapping) + (file-system-mapping->bind-mount + mapping)) + (_ #f)) + options) + (if (assoc-ref options 'no-cwd?) + '() + (list (bind-mount-spec/ro cwd)))))) + + (call-with-container mappings + (lambda () + ;; Inherit specific environment variables. + (environ environment) + + (when (getenv "HOME") + (mkdir-p (getenv "HOME"))) + + (unless (assoc-ref options 'no-cwd?) + (chdir cwd)) + + (newline) + (catch #t + (lambda () + (apply execl resolved command args)) + (lambda (key . args) + (print-exception (current-error-port) #f key args) + (exit 1)))) + + #:guest-uid 1000 + #:guest-gid 1000 + #:namespaces (safe-namespaces safe)))))))))) -- 2.47.1 From debbugs-submit-bounces@debbugs.gnu.org Wed Jan 15 17:15:07 2025 Received: (at 75595) by debbugs.gnu.org; 15 Jan 2025 22:15:08 +0000 Received: from localhost ([127.0.0.1]:59075 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tYBfH-0002pj-Aj for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:07 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:60080) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tYBfE-0002lF-IP for 75595@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:04 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBf9-00042F-9m; Wed, 15 Jan 2025 17:14:59 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=JMTiwgJyG2Yl+3Y/gtJm+iaI0vT9Pc+7ZIgV+MplzE4=; b=kfT6Z5dpgfs/zpFQGhmE llzTLyQksJ1RQj82n2sPXDaAyon4PsaDI447aB4EB4gM8p8GMNUHnpV7n1ms6iVuU9i6LRtxGs7O9 +XXrZQuGqn2olPBeb/8+ifQ8uqUk++7WR+d0/VjjkyyY+Awj28ocTMfCaHPOS1+G6XbTxlOHkU/oO +7n1943O6cSbuzDbJtR4XCbeOOLBhqb5FJowysReXiXkvaeen9SEqaeAE9SDHE7NVAHvayKc4b1HK Hio5kbgYymLrlAuaWkqRDy8kDLVTzclyzHjYfIXUWl8oPMKXaGlBVf6iXxnq5Aatfo+cJfv/mQVjD db9gvbIfu8/PrA==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= To: 75595@debbugs.gnu.org Subject: [PATCH 2/4] =?UTF-8?q?tests:=20Make=20=E2=80=98inferior-eval-with?= =?UTF-8?q?-store=E2=80=99=20test=20more=20robust.?= Date: Wed, 15 Jan 2025 23:14:48 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75595 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) * tests/inferior.scm ("inferior-eval-with-store"): Use ‘random-text’ for the store item’s body. Change-Id: Ia39e276955e1836a0272713ff25c4490273c666f --- tests/inferior.scm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/inferior.scm b/tests/inferior.scm index 963d405e33..11a27c0006 100644 --- a/tests/inferior.scm +++ b/tests/inferior.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018-2022 Ludovic Courtès +;;; Copyright © 2018-2022, 2025 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -27,6 +27,8 @@ (define-module (test-inferior) #:use-module (gnu packages bootstrap) #:use-module (gnu packages guile) #:use-module (gnu packages sqlite) + #:autoload (gcrypt hash) (sha256) + #:autoload (rnrs bytevectors) (string->utf8) #:use-module (srfi srfi-1) #:use-module (srfi srfi-34) #:use-module (srfi srfi-64) @@ -220,14 +222,15 @@ (define (manifest-entry->list entry) (close-inferior inferior) result)) -(test-equal "inferior-eval-with-store" - (add-text-to-store %store "foo" "Hello, world!") +(test-assert "inferior-eval-with-store" (let* ((inferior (open-inferior %top-builddir - #:command "scripts/guix"))) - (inferior-eval-with-store inferior %store - '(lambda (store) - (add-text-to-store store "foo" - "Hello, world!"))))) + #:command "scripts/guix")) + (text (random-text))) + (string=? (inferior-eval-with-store inferior %store + `(lambda (store) + (add-text-to-store store "foo" + ,text))) + (store-path "text" (sha256 (string->utf8 text)) "foo")))) (test-assert "inferior-eval-with-store, &store-protocol-error" (let* ((inferior (open-inferior %top-builddir -- 2.47.1 From debbugs-submit-bounces@debbugs.gnu.org Wed Jan 15 17:15:16 2025 Received: (at 75595) by debbugs.gnu.org; 15 Jan 2025 22:15:16 +0000 Received: from localhost ([127.0.0.1]:59080 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tYBfQ-0002sP-27 for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:16 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36434) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tYBfF-0002lH-ST for 75595@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:06 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBfA-00042T-Jl; Wed, 15 Jan 2025 17:15:00 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=EEmkrxEMwEH54raUCy3OqS3sH9z13xWJZZYF6ieEMmU=; b=Kg50xm9u2KiF5Sh3Sb7N KM8LIgaz74pqQ0Mw6dWn4hooFObcQrQNul3M9zqFKoiYflXQb6pOfRIU43x8Ka9y0PuwbyIzDrGLj mm6emc87CCqrd1N2YiQZe0Z+lZHbQP4i4hv6aPe7q98Big4EKd2slPaNbepofQnHJWVbDSkhbgm9C e7FhGpY4Uq9py0Tfswccto05HxTT88/5IkPkIdsPOe4F2UeIVGiPUhGtGsyr2daP1QzZ7PD7Ykjr7 DZ4wzecC7p+rOdxzhUoWInsq0TdRNZWQAl6Ea8iaJIijCcq0zm9oZNvZtQHxRBBMinn57LrV1C1Wy DtT8Mvo9CwsrWQ==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= To: 75595@debbugs.gnu.org Subject: [PATCH 3/4] inferior: Store the bridge directory name in . Date: Wed, 15 Jan 2025 23:14:49 +0100 Message-ID: <5175258f93e27140a2fcc0d1f23e396c682091da.1736977759.git.ludo@gnu.org> X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines , Josselin Poiret , Ludovic Courtès , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75595 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= , Christopher Baines X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) * guix/inferior.scm ()[bridge-directory]: New field. (port->inferior): Add #:bridge-directory and honor it. (close-inferior): Delete the bridge directory. (allocate-temporary-directory, inferior-bridge-directory): New procedures. (open-store-bridge!): Use it instead of ‘call-with-temporary-directory’. Co-authored-by: Christopher Baines Change-Id: Ie469e3f272f29054cc50b1e1afb2784521c2e2e2 --- guix/inferior.scm | 68 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/guix/inferior.scm b/guix/inferior.scm index 8066cce2fc..ead6148667 100644 --- a/guix/inferior.scm +++ b/guix/inferior.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2018-2024 Ludovic Courtès +;;; Copyright © 2018-2025 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -36,6 +36,7 @@ (define-module (guix inferior) &store-protocol-error)) #:use-module ((guix derivations) #:select (read-derivation-from-file)) + #:autoload (guix build syscalls) (mkdtemp!) #:use-module (guix gexp) #:use-module (guix search-paths) #:use-module (guix profiles) @@ -113,13 +114,15 @@ (define-module (guix inferior) ;; Inferior Guix process. (define-record-type - (inferior pid socket close version packages table - bridge-socket) + (inferior pid socket close version bridge-directory + packages table bridge-socket) inferior? (pid inferior-pid) (socket inferior-socket) (close inferior-close-socket) ;procedure (version inferior-version) ;REPL protocol version + (bridge-directory %inferior-bridge-directory ;#f | file name + set-inferior-bridge-directory!) (packages inferior-package-promise) ;promise of inferior packages (table inferior-package-table) ;promise of vhash @@ -233,6 +236,7 @@ (define* (port->inferior pipe #:optional (close close-port)) (match (read pipe) (('repl-version 0 rest ...) (letrec ((result (inferior 'pipe pipe close (cons 0 rest) + #f ;bridge directory (delay (%inferior-packages result)) (delay (%inferior-package-table result)) #f))) @@ -318,7 +322,14 @@ (define (close-inferior inferior) ;; Close and delete the store bridge, if any. (when (inferior-bridge-socket inferior) - (close-port (inferior-bridge-socket inferior))))) + (close-port (inferior-bridge-socket inferior))) + + ;; Delete the store bridge socket directory. + (when (%inferior-bridge-directory inferior) + (false-if-exception + (delete-file (in-vicinity (%inferior-bridge-directory inferior) + "inferior"))) + (rmdir (%inferior-bridge-directory inferior))))) ;; Non-self-quoting object of the inferior. (define-record-type @@ -656,6 +667,20 @@ (define (proxy inferior store) ;adapted from (guix ssh) (memq response-port reads)) (loop)))))) +(define (allocate-temporary-directory) + "Return the name of a fresh temporary directory." + (let* ((directory (or (getenv "TMPDIR") "/tmp")) + (template (string-append directory "/guix-inferior.XXXXXX"))) + (mkdtemp! template))) + +(define (inferior-bridge-directory inferior) + "Return the name of the directory shared between INFERIOR and its host to +contain the \"store bridge\"." + (or (%inferior-bridge-directory inferior) + (let ((directory (allocate-temporary-directory))) + (set-inferior-bridge-directory! inferior directory) + directory))) + (define (open-store-bridge! inferior) "Open a \"store bridge\" for INFERIOR--a named socket in /tmp that will be used to proxy store RPCs from the inferior to the store of the calling @@ -664,25 +689,24 @@ (define (open-store-bridge! inferior) ;; its store. This ensures the inferior uses the same store, with the same ;; options, the same per-session GC roots, etc. ;; FIXME: This strategy doesn't work for remote inferiors (SSH). - (call-with-temporary-directory - (lambda (directory) - (chmod directory #o700) - (let ((name (string-append directory "/inferior")) - (socket (socket AF_UNIX SOCK_STREAM 0))) - (bind socket AF_UNIX name) - (listen socket 2) + (let ((directory (inferior-bridge-directory inferior))) + (chmod directory #o700) + (let ((name (string-append directory "/inferior")) + (socket (socket AF_UNIX SOCK_STREAM 0))) + (bind socket AF_UNIX name) + (listen socket 2) - (send-inferior-request - `(define %bridge-socket - (let ((socket (socket AF_UNIX SOCK_STREAM 0))) - (connect socket AF_UNIX ,name) - socket)) - inferior) - (match (accept socket) - ((client . address) - (close-port socket) - (set-inferior-bridge-socket! inferior client))) - (read-inferior-response inferior))))) + (send-inferior-request + `(define %bridge-socket + (let ((socket (socket AF_UNIX SOCK_STREAM 0))) + (connect socket AF_UNIX ,name) + socket)) + inferior) + (match (accept socket) + ((client . address) + (close-port socket) + (set-inferior-bridge-socket! inferior client))) + (read-inferior-response inferior)))) (define (ensure-store-bridge! inferior) "Ensure INFERIOR has a connected bridge." -- 2.47.1 From debbugs-submit-bounces@debbugs.gnu.org Wed Jan 15 17:15:17 2025 Received: (at 75595) by debbugs.gnu.org; 15 Jan 2025 22:15:17 +0000 Received: from localhost ([127.0.0.1]:59082 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tYBfR-0002sa-03 for submit@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:17 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:36440) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tYBfH-0002lt-BX for 75595@debbugs.gnu.org; Wed, 15 Jan 2025 17:15:08 -0500 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tYBfC-00042x-1L; Wed, 15 Jan 2025 17:15:02 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-Version:References:In-Reply-To:Date:Subject:To: From; bh=rQnzBH2YYtmHCRWCZdYn9Ha9Qi4HOLtOX+vGS0/Aco0=; b=eydUVbvZm2wImr5U6D2G vaCocnBxkednjtR+ja1X4g6H6p37sBhaPn85fiZ6CY29HoOgKr+JWLZhujI+G8ljJcGrFxHue2qk+ RFJPopmc2Ali1G//Dm/FPMHkLp6FYM6k3TSmdEqdHqry9Vxo2jXpgT330HIip1FjQ13HRrjjhYIvq vuzgAK+XI9tKMKf4WSkFwj2wP/oiYZf6dw5xKUPwISHFMNsVZajvpfHrTDsuVE2doL2WGquUh7n0F hOJWdj8GEixEC+aDdTeb3efM0hhYT0iw0nM+HywLmu6mLeaBdjttCbpqMYjYOcqkE8kafB44UFSIP Cf90inREYwta/Q==; From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= To: 75595@debbugs.gnu.org Subject: [PATCH 4/4] inferior: Allow running inferiors in a container. Date: Wed, 15 Jan 2025 23:14:50 +0100 Message-ID: X-Mailer: git-send-email 2.47.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Debbugs-Cc: Christopher Baines , Josselin Poiret , Ludovic Courtès , Mathieu Othacehe , Simon Tournier , Tobias Geerinckx-Rice Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 75595 Cc: =?UTF-8?q?Ludovic=20Court=C3=A8s?= X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) * guix/inferior.scm (container-command-wrapper): New procedures. (open-bidirectional-pipe): Add #:isolated? and #:bridge-directory. Call ‘container-command-wrapper’ when #:isolated? is true. Adjust the argument to ‘spawn’ and ‘execlp’ accordingly. (inferior-pipe): Add #:isolated? and #:bridge-directory; pass them on to ‘open-bidirectional-pipe’. (port->inferior): Add #:bridge-directory and honor it. (open-inferior): Add #:isolated? and honor it. Call ‘allocate-temporary-directory’ when #:isolated? is true. Change-Id: Ie0a56de59aac0611d478bda858ab75f48a0853ff --- guix/inferior.scm | 118 +++++++++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 34 deletions(-) diff --git a/guix/inferior.scm b/guix/inferior.scm index ead6148667..a74e9d8665 100644 --- a/guix/inferior.scm +++ b/guix/inferior.scm @@ -36,6 +36,7 @@ (define-module (guix inferior) &store-protocol-error)) #:use-module ((guix derivations) #:select (read-derivation-from-file)) + #:autoload (guix describe) (current-profile) #:autoload (guix build syscalls) (mkdtemp!) #:use-module (guix gexp) #:use-module (guix search-paths) @@ -139,13 +140,37 @@ (define (write-inferior inferior port) (set-record-type-printer! write-inferior) -(define (open-bidirectional-pipe command . args) +(define (container-command-wrapper command bridge-directory) + "Return a command (list of strings) wrapping COMMAND such that it is spawned +in a new container that shared BRIDGE-DIRECTORY with the host." + (let ((guix (or (and=> (current-profile) + (cut string-append <> "/bin/guix")) + "guix"))) + `(,guix "container" "run" "--bare" "--feature=guix" "--no-cwd" + ,(string-append "--expose=" bridge-directory) + "--" + ,@command))) + +(define* (open-bidirectional-pipe command args + #:key isolated? bridge-directory) "Open a bidirectional pipe to COMMAND invoked with ARGS and return it, as a regular file port (socket). +When ISOLATED? is true, run COMMAND in a container that only shares +BRIDGE-DIRECTORY with the host. + This is equivalent to (open-pipe* OPEN_BOTH ...) except that the result is a regular file port that can be passed to 'select' ('open-pipe*' returns a custom binary port)." + (define wrap + ;; Optionally wrap the command so it is spawned via 'guix container run'. + ;; This is not as elegant as using 'call-with-container' directly, but the + ;; advantage is that it allows us to use 'posix_spawn' below, thus making + ;; it reliable in a multi-threaded context. + (if isolated? + (cut container-command-wrapper <> bridge-directory) + identity)) + ;; Make sure the sockets are close-on-exec; failing to do that, a second ;; inferior (for instance) would inherit the underlying file descriptor, and ;; thus (close-port PARENT) in the original process would have no effect: @@ -156,12 +181,14 @@ (define (open-bidirectional-pipe command . args) (let* ((void (open-fdes "/dev/null" O_WRONLY)) (pid (catch 'system-error (lambda () - (spawn command (cons command args) - #:input child - #:output child - #:error (if (file-port? (current-error-port)) - (current-error-port) - void))) + (match (wrap (cons command args)) + ((and (command . _) args) + (spawn command args + #:input child + #:output child + #:error (if (file-port? (current-error-port)) + (current-error-port) + void))))) (const #f)))) ;can't exec, for instance ENOENT (close-fdes void) (close-port child) @@ -187,22 +214,31 @@ (define (open-bidirectional-pipe command . args) 2))) (dup2 (open-fdes "/dev/null" O_WRONLY) 2)) - (apply execlp command command args)) + (match (wrap (cons command args)) + ((and (command . _) args) + (apply execlp command args)))) (lambda () (primitive-_exit 127)))) (pid (close-port child) (values parent pid))))))) -(define* (inferior-pipe directory command error-port) +(define* (inferior-pipe directory command error-port + #:key isolated? bridge-directory) "Return two values: an input/output pipe on the Guix instance in DIRECTORY and its PID. This runs 'DIRECTORY/COMMAND repl' if it exists, or falls back -to some other method if it's an old Guix." - (let ((pipe pid (with-error-to-port error-port - (lambda () - (open-bidirectional-pipe - (string-append directory "/" command) - "repl" "-t" "machine"))))) +to some other method if it's an old Guix. + +When ISOLATED? is true, run COMMAND in a container that only shares +BRIDGE-DIRECTORY with the host." + (let* ((bridge-directory (and isolated? bridge-directory)) + (pipe pid (with-error-to-port error-port + (lambda () + (open-bidirectional-pipe + (string-append directory "/" command) + '("repl" "-t" "machine") + #:isolated? isolated? + #:bridge-directory bridge-directory))))) (if (eof-object? (peek-char pipe)) (begin (close-port pipe) @@ -213,30 +249,33 @@ (define* (inferior-pipe directory command error-port) (lambda () (open-bidirectional-pipe "guile" - "-L" (string-append directory "/share/guile/site/" - (effective-version)) - "-C" (string-append directory "/share/guile/site/" - (effective-version)) - "-C" (string-append directory "/lib/guile/" - (effective-version) "/site-ccache") - "-c" - (object->string - `(begin - (primitive-load ,(search-path %load-path - "guix/repl.scm")) - ((@ (guix repl) machine-repl)))))))) + (list "-L" (string-append directory "/share/guile/site/" + (effective-version)) + "-C" (string-append directory "/share/guile/site/" + (effective-version)) + "-C" (string-append directory "/lib/guile/" + (effective-version) "/site-ccache") + "-c" + (object->string + `(begin + (primitive-load ,(search-path %load-path + "guix/repl.scm")) + ((@ (guix repl) machine-repl))))) + #:isolated? isolated? + #:bridge-directory bridge-directory)))) (values pipe pid)))) -(define* (port->inferior pipe #:optional (close close-port)) +(define* (port->inferior pipe #:optional (close close-port) + #:key bridge-directory) "Given PIPE, an input/output port, return an inferior that talks over PIPE. PIPE is closed with CLOSE when 'close-inferior' is called on the returned -inferior." +inferior. Associate the new inferior with BRIDGE-DIRECTORY." (setvbuf pipe 'line) (match (read pipe) (('repl-version 0 rest ...) (letrec ((result (inferior 'pipe pipe close (cons 0 rest) - #f ;bridge directory + bridge-directory (delay (%inferior-packages result)) (delay (%inferior-package-table result)) #f))) @@ -306,14 +345,25 @@ (define* (port->inferior pipe #:optional (close close-port)) (define* (open-inferior directory #:key (command "bin/guix") - (error-port (%make-void-port "w"))) + (error-port (%make-void-port "w")) + isolated?) "Open the inferior Guix in DIRECTORY, running 'DIRECTORY/COMMAND repl' or -equivalent. Return #f if the inferior could not be launched." - (let ((pipe pid (inferior-pipe directory command error-port))) +equivalent. Return #f if the inferior could not be launched. + +When ISOLATED? is true, run COMMAND in a container isolated from the host." + ;; When running the command in a container, allocate the directory that will + ;; contain the "bridge socket" upfront so it can be bind-mounted in the + ;; container. + (let* ((bridge-directory (and isolated? + (allocate-temporary-directory))) + (pipe pid (inferior-pipe directory command error-port + #:isolated? isolated? + #:bridge-directory bridge-directory))) (port->inferior pipe (lambda (port) (close-port port) - (waitpid pid))))) + (waitpid pid)) + #:bridge-directory bridge-directory))) (define (close-inferior inferior) "Close INFERIOR." -- 2.47.1 From debbugs-submit-bounces@debbugs.gnu.org Sun Feb 02 12:22:22 2025 Received: (at submit) by debbugs.gnu.org; 2 Feb 2025 17:22:22 +0000 Received: from localhost ([127.0.0.1]:36063 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1tedfq-0001Cl-AU for submit@debbugs.gnu.org; Sun, 02 Feb 2025 12:22:22 -0500 Received: from lists.gnu.org ([2001:470:142::17]:55326) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1tedfn-0001CW-Mv for submit@debbugs.gnu.org; Sun, 02 Feb 2025 12:22:20 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1tedfh-0000U0-S5 for guix-patches@gnu.org; Sun, 02 Feb 2025 12:22:14 -0500 Received: from mira.cbaines.net ([2a01:7e00:e000:2f8:fd4d:b5c7:13fb:3d27]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tedff-0002Po-Ky; Sun, 02 Feb 2025 12:22:13 -0500 Received: from localhost (unknown [IPv6:2001:67c:1810:f055:2305:6814:cba7:67bc]) by mira.cbaines.net (Postfix) with ESMTPSA id 82CA827BBE2; Sun, 2 Feb 2025 17:22:04 +0000 (GMT) Received: from fang (localhost [127.0.0.1]) by localhost (OpenSMTPD) with ESMTP id 745b2637; Sun, 2 Feb 2025 17:22:03 +0000 (UTC) From: Christopher Baines To: Ludovic =?utf-8?Q?Court=C3=A8s?= Subject: Re: [PATCH 0/4] 'guix container run' and isolated inferiors In-Reply-To: ("Ludovic =?utf-8?Q?Court?= =?utf-8?Q?=C3=A8s=22's?= message of "Wed, 15 Jan 2025 23:13:38 +0100") References: Date: Sun, 02 Feb 2025 18:22:01 +0100 Message-ID: <8734gwntxi.fsf@cbaines.net> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" Received-SPF: pass client-ip=2a01:7e00:e000:2f8:fd4d:b5c7:13fb:3d27; envelope-from=mail@cbaines.net; helo=mira.cbaines.net X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 0.9 (/) X-Debbugs-Envelope-To: submit Cc: Josselin Poiret , guix-patches@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.1 (/) --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Ludovic Court=C3=A8s writes: > You might remember that back in 2018, I sent a =E2=80=98guix run=E2=80=99= command > that would let you run programs in a container with hopefully > exactly the authority it needs: > > https://lists.gnu.org/archive/html/help-guix/2018-01/msg00108.html > > This patch series adds an improved version of that command > as =E2=80=98guix container run=E2=80=99. By default, it figures out what= extra > authority to give: for X11 programs, it lets =E2=80=98DISPLAY=E2=80=99 th= rough and > bind-mounts /tmp/.X11-unix, for DBus programs it maps /etc/machine-id, > and so on. > > Alternatively, you can use =E2=80=98--bare=E2=80=99 and you get a bare co= ntainer in > the style of =E2=80=98guix shell -C=E2=80=99. It supports =E2=80=98-N=E2= =80=99, =E2=80=98--expose=E2=80=99, and other > options found in =E2=80=98guix shell -C=E2=80=99 and related commands. > > ~~~ > > But really, my initial motivation was to run inferiors in a container. > Christopher implemented that years ago, using (gnu build linux-container): > > https://issues.guix.gnu.org/34638 > > There were small issues that needed to be addressed, but the main > problem I would have with it today is the fact that we=E2=80=99d call =E2= =80=98clone=E2=80=99 > directly, making it effectively unusuable in a multi-threaded context > (see horror story in , which led > to the implementation of =E2=80=98spawn=E2=80=99 in Guile by Josselin.) > > So I thought that by having a command-line interface to > =E2=80=98call-with-container=E2=80=99 (!), which is essentially what =E2= =80=98guix container run=E2=80=99 > is, we would be able to use =E2=80=98posix_spawn=E2=80=99 to run that CLI= and spawn > inferiors without risk. Incidentally, it is rather simple to implement > and reason about. > > This is what the last patch does. I didn=E2=80=99t add tests: the =E2=80= =98guix=E2=80=99 binary > needs to be in the store, which makes it hard to test. But here=E2=80=99= s an > example session: > > --8<---------------cut here---------------start------------->8--- > $ ./pre-inst-env guile -q > GNU Guile 3.0.9 > Copyright (C) 1995-2023 Free Software Foundation, Inc. > > Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'. > This program is free software, and you are welcome to redistribute it > under certain conditions; type `,show c' for details. > > Enter `,help' for help. > scheme@(guile-user)> ,use(guix inferior) > scheme@(guile-user)> (open-inferior "/home/ludo/.config/guix/current" #:i= solated? #t) > $1 =3D # > scheme@(guile-user)> (inferior-eval '(use-modules (ice-9 ftw)) $1) > $2 =3D #> > scheme@(guile-user)> (inferior-eval '(scandir "/home/ludo") $1) > $3 =3D ("." ".." ".cache") > scheme@(guile-user)> ,use(guix) > scheme@(guile-user)> (define s (open-connection)) > scheme@(guile-user)> (inferior-eval-with-store $1 s `(lambda (s) (add-tex= t-to-store s "isolated" "hi from inferior!"))) > $4 =3D "/gnu/store/kvnxfbcwn5sdr02y75v2w4fswns0ql8d-isolated" > --8<---------------cut here---------------end--------------->8--- > > Thoughts? I've had a rough look over the changes and they look good to me. Thanks, Chris --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQKlBAEBCgCPFiEEPonu50WOcg2XVOCyXiijOwuE9XcFAmefqblfFIAAAAAALgAo aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDNF ODlFRUU3NDU4RTcyMEQ5NzU0RTBCMjVFMjhBMzNCMEI4NEY1NzcRHG1haWxAY2Jh aW5lcy5uZXQACgkQXiijOwuE9XcV6xAAqqFl19gVF0w6/Dl6ObEtDhbudF8xKJgc kCYjsyMGGo3x4c3OAmZbTQgLPtj3ajHyhoDkWGuqnJQJQ7hiAeokR5BfFmxotc2r a0EkDhTBQpAmmMHk0UUsNCc3j5lHaUTf+jowVeg6R36tpOSQrzdlJd1hNBOeJYmf cYY5rN0p7nHapAZgBwPVCt5qY/GQEa1f+IIg8YQ726mOoT5SbdbbP2jCUOjF97ht eVnj4BMCBhQsf/m+041ZuPg/C7LhOfXYvqyK7hGu7Swai6oM8FUUgfEGcI4vi0TL yE0A08g+RdWGhuSLnKYLLqQYIZwM007bNkl7iaFaHxT9ebqy7pFQ5VDvWpdCwYhE e6mWM2dJxnhxXkjucXSzj97aqyJvAh2cLgfjlwWDwZSJbfZOYs4Xj5ehEc9vVvES i4zDlB1QfynCq9vugayoBY/9MimsInwFPZ/MbFGdl3l780425mtuZ2SPCTQRi2zs Tf4B4hRSNQDbnxLUeNtcw+XuUGGuzNPqXA5JzfM+M27YkaZbbjjKkq0VWea5wL3g 4bM8ShKa25ad+5rSwOcF4XaIwoxaXoWfBRK/qrjQpFT4ImCyfqi27SUFmQoEzQ0h i9G47H0uAXBtOobVgzdfQhdxu9taQsW9AraHdVjv2GqWnUMjQU3l3BRwTnFznqzB ELVSB2qzC1A= =sJ2V -----END PGP SIGNATURE----- --=-=-=--