Search code examples
pythonpopenhaskell-snap-frameworksnapcraft

Confine python popen child snap container


I try to confing a python subprocess.Popen process to a snap package I built.

To learn about snap package creation I decided to build a snap container for a markdown editor, built in python, I regularly use. I managed to create a snapcraft.yaml file, which I am able to install and start the editor with successfully.

However, the editor allows the user to open a second window, e.g. to edit a second file. Internally it calls subprocess.Popen(sys.argv[0]), so it creates a child process of itself.
I fail to confine this new process to the snap itself.
argv0 on both parent and child is set to /snap/remarkable-deadolus/x34/bin/remarkable, which I verified by creating some debug output.

The new process fails to find some libraries, which apparently were successfully found (because the snap package installed them) by the main process:

Traceback (most recent call last):
  File "/snap/remarkable-deadolus/x34/bin/remarkable", line 72, in <module>
    import remarkable
  File "/snap/remarkable-deadolus/x34/remarkable/__init__.py", line 26, in <module>
    import gi
ModuleNotFoundError: No module named 'gi'

When investigating I found that some (environment) variables seem to differ between the creation of the main snap process and its children. The call to print(sys.prefix) in the parent produces /snap/remarkable-deadolus/x33/usr. In the child however it produces /usr.

So my question is how can I confine the child processes of a python snap program to the snap package?

Here is my progress so far: Deadolus Github Remarkable with snapcraft.yaml file

For reference, my commands to build and then run the snap package are:

snapcraft --debug
sudo snap install --devmode *.snap
remarkable-deadolus

In the snapcraft.yaml file I enabled strict confinement by adding

confinement: strict

Solution

  • The bin/remarkable file in your git repository begins with:

    #! /usr/bin/python3
    

    But the snapcraft.yaml file shows it being invoked with a Python interpreter that is shipped within your snap:

    apps:
      remarkable-deadolus:
        command: usr/bin/python3 $SNAP/bin/remarkable
    

    The two interpreters have different import paths, so the parent and child processes can see different sets of Python modules.

    One solution is to change how you launch the subprocess. The sys.executable variable holds the path to the currently running Python interpreter, so you could try changing the Popen call to:

    subprocess.Popen([sys.executable, sys.argv[0]])