Snap works as strict, devmode, not as classic

I have a strange snap I’ve built which runs fine as strict and devmode confinement, but not as a classic snap. When run as classic the snap spins forever, and never completes. When run as strict or devmode it works pretty much as expected. This snap needs to be classic though due to the need to write to arbitrary locations, so I’m keen to understand a) why it doesn’t work as a classic snap, and b) how to fix it.

Any ideas why this would spin forever as a classic snap?

name: rustup-init
version: '1.11.0'
summary: The Rust toolchain installer
description: |
  rustup installs The Rust Programming Language from the official
  release channels, enabling you to easily switch between stable,
  beta, and nightly compilers and keep them updated. It makes
  cross-compiling simpler with binary builds of the standard
  library for common platforms. And it runs on all platforms
  Rust supports, including Windows..

grade: stable
confinement: strict

apps:
  rustup-init:
    command: rustup-init 
    plugs:
      - network

parts:
  rustup:
    plugin: rust
    source: https://github.com/rust-lang-nursery/rustup.rs.git
    source-tag: '1.11.0'
    source-type: git
    build-packages:
      - libssl-dev
      - make
      - pkg-config
1 Like

Here’s the strace. https://people.canonical.com/~alan/rustup-init.trace.gz

Have you tried disabling patchelf?

Yes. No change.

1 Like

Can you strace it and provide some logs here (in the case where it doesn’t work). Does the same binary work outside of snap context, just on your regular system?

The strace is linked above. There is nothing logged when it doesn’t work.

1 Like

Looks like rustup-init is reexecuting itself over and over again.

I missed that message somehow.

Looking at the strace everything is fine until this:

[pid 12850] execve("/snap/rustup-init/x1/command-rustup-init.wrapper", ["/snap/rustup-init/x1/command-rus"...], 0xc4200a2e00 /* 106 vars *//usr/bin/strace: Process 13699 attached
 <unfinished ...>
[pid 13699] arch_prctl(ARCH_SET_FS, 0xc42004c490) = 0

This is where we effectively run the real meat of the snap. I don’t know much about that system call. I recall it could affect thread local storage somehow.

Does it work if you run it directly?

Yup, the same binary works fine if you run it either strict, devmode or outside of confinement completely.

1 Like

Have you tried running that binary (outside of snap) in a Ubuntu 16.04 VM?

Yes, works fine.

Given @mborzecki’s comment, the solution is to change command to be command: $SNAP/rustup-init.

The issue is that /snap/bin is in PATH. Alternatively, try adding adapter: none to the apps entry.

Tried both. If I use command: $SNAP/bin/rustup-init

Snapcraft crashes.

FileNotFoundError: [Errno 2] No such file or directory: '/root/build_rustup-init/prime/$SNAP/bin/rustup-init'

With adapter: none it fails to install.

error: cannot install snap file: snap is unusable due to missing files; contact developer

With adapter: none you need to use the relative path inside the snap, I thought the messaging was fixed on the snapcraft side. @Chipaca, was it?

1 Like

Current status.

apps:
  rustup-init:
    adapter: none
    command: /usr/bin/env $SNAP/bin/rustup-init

error: cannot install snap file: snap is unusable due to missing files; contact developer

oh, you cannot use /usr/bin/env with adaptor: none as snapd enforces the command to be executed to be inside the snap.

Success!

apps:
  rustup-init:
    adapter: none
    command: ./bin/rustup-init
$ snap install rustup-init_1.11.0_amd64.snap --dangerous --classic
rustup-init 1.11.0 installed
alan@hal:~/src/rustup$ rustup-init 

Welcome to Rust!

This will download and install the official compiler for the Rust programming 
language, and its package manager, Cargo.

It will add the cargo, rustc, rustup and other commands to Cargo's bin 
directory, located at:

  /home/alan/.cargo/bin

This path will then be added to your PATH environment variable by modifying the
profile file located at:

  /home/alan/.profile

You can uninstall at any time with rustup self uninstall and these changes will
be reverted.

Current installation options:

   default host triple: x86_64-unknown-linux-gnu
     default toolchain: stable
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation
^C

Thanks! :smiley:

1 Like

Ah, so the issue is that the command that snapcraft generates we get a loop foo -> snap run foo -> foo -> snap run foo -> foo -> …

We had this bug twice already, I wonder what happened that it is back again.

Maybe we should catch, or at least warn about bare command: foo as part of snap validation?

TBH I would really, really like if we could just do this (I know this is not backwards compatible):

This runs bin/foo from the snap itself.

apps:
  foo:
    command: $SNAP/bin/foo

This runs /bin/bar from the base snap

apps:
  bar:
    command: /bin/bar
1 Like