Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nix: Environment isn't passed to controllers started with artiq_ctlmgr #7

Closed
drewrisinger opened this issue Dec 15, 2020 · 9 comments
Closed

Comments

@drewrisinger
Copy link

drewrisinger commented Dec 15, 2020

Summary

Starting the ARTIQ no_hardware examples fails on Ubuntu (Nix).

Steps to Reproduce

Use the following my-shell.nix file with latest versions of nixos-20.03 & artiq-full:
EDIT: taken from ARTIQ manual, extra python packages are needed for correct python packages for no_hardware/device_db.py so it (shouldn't) fail.

let
  pkgs = import <nixpkgs> {};
  artiq-full = import <artiq-full> { inherit pkgs; };
in
  pkgs.mkShell {
    buildInputs = [
      (pkgs.python3.withPackages(ps: [
        artiq-full.artiq
        artiq-full.artiq-comtools

        ps.numpy
        ps.scipy
        ps.numba
        ps.setuptools
        (ps.matplotlib.override { enableQt = true; })
      ]))
    ];
  }

(Assuming ARTIQ Nix derivations & binaries are installed as specified in manual).
Get the ARTIQ repo w/ examples & start

git clone https://github.com/m-labs/artiq
nix-shell ./my-shell.nix
$ cd artiq/artiq/examples/no_hardware
$ artiq_session

Error Message (short, what I think is relevant)

[nix-shell:~/git/artiq/artiq/examples/no_hardware]$ artiq_session
ARTIQ master is now ready.
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller lda failed to start
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller lda failed to start
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller camera_sim exited
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller camera_sim exited
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds

Error Message (full, removing machine name)

Full Traceback
[nix-shell:~/git/artiq/artiq/examples/no_hardware]$ artiq_session
ARTIQ master is now ready.
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller lda failed to start
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller lda failed to start
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller camera_sim exited
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Controller camera_sim exited
WARNING:ctlmgr(PC):artiq_comtools.ctlmgr:Restarting in 5.0 seconds
Fontconfig warning: "/etc/fonts/fonts.conf", line 5: unknown element "its:rules"
Fontconfig warning: "/etc/fonts/fonts.conf", line 6: unknown element "its:translateRule"
Fontconfig error: "/etc/fonts/fonts.conf", line 6: invalid attribute 'translate'
Fontconfig error: "/etc/fonts/fonts.conf", line 6: invalid attribute 'selector'
Fontconfig error: "/etc/fonts/fonts.conf", line 7: invalid attribute 'xmlns:its'
Fontconfig error: "/etc/fonts/fonts.conf", line 7: invalid attribute 'version'
Fontconfig warning: "/etc/fonts/fonts.conf", line 9: unknown element "description"
Fontconfig error: Cannot load config file from /etc/fonts/fonts.conf
INFO:dashboard:root:ARTIQ dashboard 5.7139.a694d130 connected to ::1
qt.glx: qglx_findConfig: Failed to finding matching FBConfig for QSurfaceFormat(version 2.0, options QFlags<QSurfaceFormat::FormatOption>(), depthBufferSize -1, redBufferSize 1, greenBufferSize 1, blueBufferSize 1, alphaBufferSize -1, stencilBufferSize -1, samples -1, swapBehavior QSurfaceFormat::SingleBuffer, swapInterval 1, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::NoProfile)
No XVisualInfo for format QSurfaceFormat(version 2.0, options QFlags<QSurfaceFormat::FormatOption>(), depthBufferSize -1, redBufferSize 1, greenBufferSize 1, blueBufferSize 1, alphaBufferSize -1, stencilBufferSize -1, samples -1, swapBehavior QSurfaceFormat::SingleBuffer, swapInterval 1, colorSpace QSurfaceFormat::DefaultColorSpace, profile  QSurfaceFormat::NoProfile)
Falling back to using screens root_visual.
^CTraceback (most recent call last):
Traceback (most recent call last):
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/runpy.py", line 193, in _run_module_as_main
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
    "__main__", mod_spec)
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/runpy.py", line 85, in _run_code
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
    exec(code, run_globals)  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/artiq_comtools/artiq_ctlmgr.py", line 88, in <module>

  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/artiq/frontend/artiq_master.py", line 161, in <module>
    main()
  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/artiq_comtools/artiq_ctlmgr.py", line 84, in main
    main()
  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/artiq/frontend/artiq_master.py", line 158, in main
    loop.run_until_complete(rpc_server.wait_terminate())
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/asyncio/base_events.py", line 570, in run_until_complete
    loop.run_forever()
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/asyncio/base_events.py", line 538, in run_forever
    self.run_forever()
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/asyncio/base_events.py", line 538, in run_forever
    self._run_once()
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/asyncio/base_events.py", line 1746, in _run_once
    self._run_once()
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/asyncio/base_events.py", line 1746, in _run_once
    event_list = self._selector.select(timeout)
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/selectors.py", line 468, in select
    event_list = self._selector.select(timeout)
  File "/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/lib/python3.7/selectors.py", line 468, in select
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
    fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
Traceback (most recent call last):
  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/quamash/_unix.py", line 121, in __on_read_activated
    def __on_read_activated(self, fd):
KeyboardInterrupt
Traceback (most recent call last):
  File "/nix/store/267axcb6ns9a879vd79rjx7hpgwcjvcw-python3.7-artiq-5.7139.a694d130/bin/.artiq_session-wrapped", line 9, in <module>
    sys.exit(main())
  File "/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages/artiq/frontend/artiq_session.py", line 50, in main
    for line in iter(master.stdout.readline, ""):
KeyboardInterrupt

Just discovered this bug, and haven't had time to debug/isolate it fully. Running python -c "import artiq" from the same shell works fine.

This is an issue to me because it also prevents other controllers from being started by artiq_ctlmgr on the same machine.

@drewrisinger
Copy link
Author

@b-bondurant @lriesebos have you seen this issue?

@b-bondurant
Copy link
Contributor

@drewrisinger not that I'm aware of, but I'll take a look

@drewrisinger
Copy link
Author

@sbourdeauducq @dnadlinger is this a known bug/do you have workarounds?

My guess is that device_db.py entries of the form

'my_controller': {
    'type': 'controller',
    'host': '::1',
    'port': PORT,
    'command': 'python -m ...'
},

don't work because their python environment isn't wrapped properly (i.e. /nix/store/...-python-3.7.../bin/python doesn't have the PYTHONPATH of the downstream modules e.g. ARTIQ available)

@sbourdeauducq
Copy link
Member

INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')

The correct Python executable should have something with -env in the nix store path, e.g. /nix/store/31wbgis23naibfmpx7gc0gcpg9zhav26-python3-3.8.5-env/bin/python.
Why is it running the other one? What happens if you use nix-shell --pure my-shell.nix?

@drewrisinger
Copy link
Author

@sbourdeauducq ack, that's what flagged me to the python env wrapping.

$ git checkout release-5
$ nix-shell my-shell.nix --pure --run "cd artiq/examples/no_hardware && artiq_session"
ARTIQ master is now ready.
...
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
INFO:controller(camera_sim):print:/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3: Error while finding module specification for 'artiq.examples.remote_exec_controller' (ModuleNotFoundError: No module named 'artiq')
$ nix-shell ./my-shell.nix --run 'cat $(which artiq_session) && cat $(which artiq_ctlmgr)'
#! /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash -e
export NIX_PYTHONPREFIX='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env'
export NIX_PYTHONEXECUTABLE='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/bin/python3.7'
export NIX_PYTHONPATH='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages'
export PYTHONNOUSERSITE='true'
exec "/nix/store/267axcb6ns9a879vd79rjx7hpgwcjvcw-python3.7-artiq-5.7139.a694d130/bin/artiq_session"  "$@"
#! /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash -e
export NIX_PYTHONPREFIX='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env'
export NIX_PYTHONEXECUTABLE='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/bin/python3.7'
export NIX_PYTHONPATH='/nix/store/d2grsm7cs8j5ql8h9dhyikhqjydv5y74-python3-3.7.6-env/lib/python3.7/site-packages'
export PYTHONNOUSERSITE='true'
exec "/nix/store/i0f4f9iaapyranhmy92fw4iz6g6adl8v-python3.7-artiq-comtools-1.1/bin/artiq_ctlmgr"  "$@"
$ cat /nix/store/i0f4f9iaapyranhmy92fw4iz6g6adl8v-python3.7-artiq-comtools-1.1/bin/artiq_ctlmgr
#! /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash -e
export PATH='/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin:/nix/store/i0f4f9iaapyranhmy92fw4iz6g6adl8v-python3.7-artiq-comtools-1.1/bin:/nix/store/6ppffsymnlwy9ziw19nn4pah794g38kj-python3.7-sipyco/bin:/nix/store/qz0j7ynd2fv73hmkv8nfrj04xd4h7dcj-python3.7-numpy-1.18.1/bin:/nix/store/8dmmabfb8g3xcpsacnh4ipflkmai2465-python3.7-chardet-3.0.4/bin'${PATH:+':'}$PATH
export PYTHONNOUSERSITE='true'
exec -a "$0" "/nix/store/i0f4f9iaapyranhmy92fw4iz6g6adl8v-python3.7-artiq-comtools-1.1/bin/.artiq_ctlmgr-wrapped"  "$@"

Yeah, here's the issue^^. The PATH for /nix/store/...-artiq-comtools.../bin/artiq_ctlmgr doesn't include /nix/store/...-python3-3.7.6-env/, and artiq_session doesn't pass the wrapped python path to it. I'm not sure what to do to fix this exactly, but a couple thoughts off the top of my head, in order of least favorable -> more favorable:

  • Explicit checking for env var NIX_PYTHONPATH in artiq_ctlmgr. i.e. substitute python -> $NIX_PYTHONPREFIX.
  • modify the Nix wrapper args for artiq_session, artiq_ctlmgr, etc. to include the wrapped python path.

@dnadlinger
Copy link
Contributor

@dnadlinger is this a known bug/do you have workarounds?

Just for completeness: I am not running ARTIQ using the Nix package; rather, I just use it to prepare all the dependencies for then installing ARTIQ/… in development mode into two different venvs for our two trap nodes. This is a very suboptimal setup (among other things, it discards all the reproducibility benefits), but was the easiest way I could find to get all the executable wrappers installed. (Just setting PYTHONPATH in a Nix shell derivation to get "development mode" works for me personally, but would force all the other people to use python -m artiq.frontend.… etc. in place of the wrappers too.)

@sbourdeauducq
Copy link
Member

modify the Nix wrapper args for artiq_session, artiq_ctlmgr, etc. to include the wrapped python path.

I would prefer this solution over adding package manager specific code into ARTIQ.

@drewrisinger
Copy link
Author

drewrisinger commented Dec 22, 2020

Ok. I finally had time to track down this issue.

High-level summary:

The wrapped python environment (i.e. the one created with python3.withPackages(...)) doesn't get passed to artiq_ctlmgr.py at all. This variable is (effectively) stripped out by a combination of the script wrapper & the sitecustomize.py, as well as not being added to $PATH. So instead of seeing the wrapped python environment (e.g. /nix/store/*-python3-3.7.6-env), it only sees the base python interpreter (/nix/store/*-python3-3.7.6/bin/python3) and no added paths. The only way I've found around this is to dynamically add NIX_PYTHONPREFIX (i.e. the wrapped environment) to the PATH. More details below, along with a tested patch to https://git.m-labs.hk/M-Labs/nix-scripts that would fixes the bug locally.

Patch

Patch file below (apply with ``git am``)
From 3c681d855ac67ee5e65fda6f0c4e941230922145 Mon Sep 17 00:00:00 2001
From: Drew Risinger <drewrisinger@users.noreply.github.com>
Date: Tue, 22 Dec 2020 17:01:38 -0500
Subject: [PATCH] artiq: pass wrapped python env to subprocesses

Fixes https://github.com/m-labs/artiq-comtools/issues/7.
Basically, python subprocesses can't see all installed python packages
in a python environment because it uses the wrong Python exe (i.e. it
doesn't use the wrapped exe). This patches the PATH in the binary
wrappers (e.g. */bin/artiq_session) to include the correct python path.
---
 artiq-fast/pkgs/artiq.nix | 4 ++++
 artiq-full/extras.nix     | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/artiq-fast/pkgs/artiq.nix b/artiq-fast/pkgs/artiq.nix
index f2a89c2..78be5a0 100644
--- a/artiq-fast/pkgs/artiq.nix
+++ b/artiq-fast/pkgs/artiq.nix
@@ -21,6 +21,10 @@ python3Packages.buildPythonPackage rec {
     wrapQtApp "$out/bin/artiq_session"
   '';
 
+  # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses.
+  # Allows subprocesses using python to find all packages you have installed
+  makeWrapperArgs = [ ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' ];
+
   checkInputs = [ binutils-or1k outputcheck ];
   checkPhase =
   ''
diff --git a/artiq-full/extras.nix b/artiq-full/extras.nix
index 9f51628..bc55fc8 100644
--- a/artiq-full/extras.nix
+++ b/artiq-full/extras.nix
@@ -195,6 +195,9 @@ in
         sha256 = "165j12k9nnrkf2pv0idcv6xhnp1hnsllna4rps2dssnqgjfaw1ss";
       };
       propagatedBuildInputs = [ sipyco pkgs.python3Packages.numpy pkgs.python3Packages.aiohttp ];
+      # Modifies PATH to pass the wrapped python environment (i.e. python3.withPackages(...) to subprocesses.
+      # Allows subprocesses using python to find all packages you have installed
+      makeWrapperArgs = [ ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' ];
     };
     conda-artiq-comtools = condaBuild {
       name = "conda-artiq-comtools";
-- 
2.29.2


Details

Minimal reproduction steps

$ mkdir -p test-artiq-comtools-env/repository
$ cd test-artiq-comtools-env

Files:

device_db.py
device_db = {
    # Can be commented out to prevent stray process starting. Needs tested before finished
    "camera_sim": {
        "type": "controller",
        "host": "::1",
        "port": 6283,
        "target_name": "camera_sim",
        "command": "python3 -m artiq.examples.remote_exec_controller"
    },
    # prints the environment present for debugging
    "test_environment": {
        "type": "controller",
        "host": "::1",
        "port": 6200,
        "command": "python -c \"import os, sys, site; print(r'Environ: {{}}\\nPrefix: {{}}\\nExe: {{}}\\nSitePackages: {{}}'.format(os.environ, sys.prefix, sys.executable, site.getsitepackages()))\"",
    },
    "test_artiq_present": {
        "type": "controller",
        "host": "::1",
        "port": 6201,
        "command": "python -c \"import artiq; print('SUCCESS')\"",
    },
}
artiq_minimal.nix
let
  pkgs = import (builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/929768261a3ede470eafb58d5b819e1a848aa8bf.tar.gz";
  }) {};
  artiq-full = import /home/.../artiqpkgs.nix { inherit pkgs; }; 
  # Custom replication of MLabs hydra build process using local (modified) checkout of https://git.m-labs.hk/M-Labs/nix-scripts/src/commit/a45b6fc771693861a91059534d8618fe585ef2f6. See attached patch for mod
in
  pkgs.mkShell {
    buildInputs = [
      (pkgs.python3.withPackages(ps: [
        artiq-full.artiq
        artiq-full.artiq-comtools

        ps.numpy
        ps.numba
        ps.scipy
        ps.setuptools
      ]))
    ];
  }
Testing

nix-shell ./artiq_minimal.nix --run "artiq_session"

Tracking down the bug

Nix wraps python executables to provide the proper environment & variables, e.g. to add the NIX_PYTHON[PATH,PREFIX,EXECUTABLE] variables so that the sitecustomize.py can look for packages in the proper directories. We know that sitecustomize.py runs because e.g. NIX_PYTHONPATH isn't in the environment of the subprocess (test_environment in device_db.py).

We can look at this wrapping from within nix-shell ./artiq_minimal.nix by e.g.:

Outputting the wrapper script files
$ cat $(which artiq_ctlmgr)
#! /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash -e
export NIX_PYTHONPREFIX='/nix/store/x21yjqv9nccaca730p40iggcp5w2lsrk-python3-3.7.6-env'
export NIX_PYTHONEXECUTABLE='/nix/store/x21yjqv9nccaca730p40iggcp5w2lsrk-python3-3.7.6-env/bin/python3.7'
export NIX_PYTHONPATH='/nix/store/x21yjqv9nccaca730p40iggcp5w2lsrk-python3-3.7.6-env/lib/python3.7/site-packages'
export PYTHONNOUSERSITE='true'
exec "/nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin/artiq_ctlmgr"  "$@"

$ cat /nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin/artiq_ctlmgr 
#! /nix/store/hrpvwkjz04s9i4nmli843hyw9z4pwhww-bash-4.4-p23/bin/bash -e
export PATH='/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin:/nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin:/nix/store/1fpcnywm092zvgbs6j6kcmc7ln2v06x3-python3.7-sipyco-1.1/bin:/nix/store/qz0j7ynd2fv73hmkv8nfrj04xd4h7dcj-python3.7-numpy-1.18.1/bin:/nix/store/8dmmabfb8g3xcpsacnh4ipflkmai2465-python3.7-chardet-3.0.4/bin'${PATH:+':'}$PATH
export PYTHONNOUSERSITE='true'
exec -a "$0" "/nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin/.artiq_ctlmgr-wrapped"  "$@"

$ cat /nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin/.artiq_ctlmgr-wrapped 
#!/nix/store/r94aa2gj4drkhfvkm2p4ab6cblb6kxlq-python3-3.7.6/bin/python3.7
# -*- coding: utf-8 -*-
import sys;import site;import functools;sys.argv[0] = '/nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/bin/artiq_ctlmgr';functools.reduce(lambda k, p: site.addsitedir(p, k), ['/nix/store/d8cgxms01c7ifx59yg5bcmcx1vha97cv-python3.7-artiq-comtools-1.1/lib/python3.7/site-packages','/nix/store/1fpcnywm092zvgbs6j6kcmc7ln2v06x3-python3.7-sipyco-1.1/lib/python3.7/site-packages','/nix/store/qz0j7ynd2fv73hmkv8nfrj04xd4h7dcj-python3.7-numpy-1.18.1/lib/python3.7/site-packages','/nix/store/zj3yq7398qah5cnw75yi9h207ssfb5w9-python3.7-aiohttp-3.6.2/lib/python3.7/site-packages','/nix/store/bbicl709z65vh33nhjipm5apmsv81li8-python3.7-attrs-19.3.0/lib/python3.7/site-packages','/nix/store/8dmmabfb8g3xcpsacnh4ipflkmai2465-python3.7-chardet-3.0.4/lib/python3.7/site-packages','/nix/store/idl2413784psk7gs5b24971cc7dc2la9-python3.7-multidict-4.7.4/lib/python3.7/site-packages','/nix/store/j7k2d3rflf7yqzkglvaicvc7xyhxmahg-python3.7-async-timeout-3.0.1/lib/python3.7/site-packages','/nix/store/9skch6zxx8g1nxwb2kwjhlb9c5msahcz-python3.7-yarl-1.4.2/lib/python3.7/site-packages','/nix/store/py5py6kkf8yc3284i6v1zh1lraym2nr4-python3.7-idna-2.8/lib/python3.7/site-packages'], site._init_pathinfo());
import re
import sys
from artiq_comtools.artiq_ctlmgr import main
if __name__ == '__main__':
    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(main())

By combining this with the test output from device_db.py, we can get an idea of what and where environment variables are set.

Patching the Bug

I see 3 possible solutions to fixing this issue.

  1. Modify artiq-comtools python to pass its site packages & sys.path to subprocesses. In addition to not being desired by @sbourdeauducq above, this would probably be difficult/hacky.
  2. Allow leaking NIX_PYTHON* environment variables by modifying nixpkgs/sitecustomize.py. This is not desired b/c it explicitly goes against design decisions by the Nixpkgs team. They might be open to an option to explicitly allow leaking environment variables to subprocesses, but that's an open question.
  3. Hack the artiq-comtools Nix package to modify the path itself. This isn't very pretty, but it is repeatable due to Nix, and is a Nix solution to a problem caused by Nix. This is the solution that I chose.

Solution details:

Effectively, this looks like prepending the /nix/store/*-python3-*-env wrapped python environment to $PATH of artiq_ctlmgr and any other ARTIQ binary scripts.

However, this is a little complicated b/c the $NIX_PYTHONPATH isn't declared until "runtime" (i.e. creating the wrapped python environment happens after building e.g. the artiq-comtools package), so attempts to use standard wrapper arguments like:

buildPythonPackage {
  pname = "artiq-comtools";
  ...
  makeWrapperArgs = [ "--prefix PATH : $NIX_PYTHONPREFIX/bin" ];
}

won't work, because $NIX_PYTHONPREFIX doesn't exist, and makeWrapper prevents dynamic environment variables from being loaded at runtime by using '$ENV_VAR' bash syntax.
The workaround I found is to run a simple command before executing the python script:

makeWrapperArgs = [ ''--run 'if [ ! -z "$NIX_PYTHONPREFIX" ]; then export PATH=$NIX_PYTHONPREFIX/bin:$PATH;fi' '' ];

Conclusion

Applying the patch above should work. Tested with:

  1. Separate artiq_master && artiq_ctlmgr
  2. artiq_session
  3. python -m artiq.frontend.artiq_session

@sbourdeauducq
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants