fix(flatpak): allocate PTY on host via rio-pty-host helper#1523
Draft
daniloaguiarbr wants to merge 3 commits intoraphamorim:mainfrom
Draft
fix(flatpak): allocate PTY on host via rio-pty-host helper#1523daniloaguiarbr wants to merge 3 commits intoraphamorim:mainfrom
daniloaguiarbr wants to merge 3 commits intoraphamorim:mainfrom
Conversation
When Rio runs inside a Flatpak sandbox, the PTY created via openpty() lives in the sandbox's mount namespace and is invisible on the host. Scripts that call ttyname(0) on those FDs (e.g. /etc/profile.d/gnupg2.sh on Fedora: `export GPG_TTY=$(tty)`) fail with ENODEV and print "tty: not a tty / no such device" on first shell line. rio-pty-host is a small helper binary meant to be spawned on the host via `flatpak-spawn --host`. It allocates a new PTY in the host's mount namespace, forks the real shell as controlling-terminal owner of that PTY, and relays I/O between its stdio (the sandbox PTY slave) and the host PTY master. Since the shell now sees a /dev/pts/N that exists on the host, ttyname() resolves correctly and GPG_TTY is set as expected. The crate uses only `libc` (workspace) and `thiserror` (promoted to workspace.dependencies = "2.0.1") with no extra transitive deps. All unsafe blocks carry a `// SAFETY:` comment. Shell paths are validated as absolute to prevent PATH manipulation. Signal handling uses a static AtomicBool so there is no Arc::into_raw leak. Adds workspace member `rio-pty-host` and README describing the bundled distribution plus `~/.local/bin/` auto-install mechanism used by the teletypewriter integration (separate commit). 7 unit tests cover argv parsing, openpty validity, absolute-path enforcement, and shell spawn happy path. Known limitation (v1): SIGWINCH is not propagated to the host shell; dynamic resize is deferred to a follow-up.
The existing flatpak-spawn block in create_pty_with_spawn passes the
sandbox PTY slave directly to the host bash. That works for the basic
shell, but bash login init scripts (notably /etc/profile.d/gnupg2.sh on
Fedora) call ttyname(0) which fails with ENODEV because /dev/pts/N
created in the sandbox does not exist in the host's mount namespace.
When a Flatpak sandbox is detected, this change now prefers to invoke
the rio-pty-host helper on the host (added in the previous commit). The
helper creates a fresh PTY in the host's namespace and runs the shell
there, so ttyname() resolves correctly and GPG_TTY is populated.
Behaviour:
- New module `unix::flatpak` caches both the `/.flatpak-info` probe and
the resolved path of `~/.host/.local/bin/rio-pty-host` via OnceLock.
- On first call inside Flatpak, `caminho_rio_pty_host()` checks for an
existing `~/.local/bin/rio-pty-host` on the host; if absent, it
installs the bundled `/app/bin/rio-pty-host` by piping it through
`flatpak-spawn --host` and atomically renaming
`mktemp` -> chmod +x -> mv -f. Atomicity is provided by `rename(2)`
on the same filesystem, so concurrent Rio instances are safe.
- create_pty_with_spawn now branches:
1. If rio-pty-host is available, spawn it on the host with
`<COLS> <ROWS> <SHELL> -l`. is_controling_terminal stays false
because the helper sets up TIOCSCTTY itself.
2. Otherwise it falls back to the legacy direct shell invocation
and emits a tracing::warn explaining the cosmetic GPG_TTY
limitation.
- `$SHELL` retrieved via flatpak-spawn is now defensively trimmed and
falls back to /bin/sh when empty.
3 unit tests cover the OnceLock-bound detection path, the missing
`/app/bin` source path, and the home-host probe being panic-free. The
Flatpak detection test is `#[ignore]`-d because OnceLock cannot be
reset between tests in the same process; it should be exercised via
`assert_cmd` subprocesses.
This change is no-op outside of Linux Flatpak; macOS and FreeBSD code
paths are untouched.
Add right-click context menu overlay with 7 actions (Copy/Paste/SelectAll/ SplitRight/SplitDown/NewTab/CloseTab) rendered via sugarloaf at z-order 21 above CommandPalette. Menu items are hardcoded in English for upstream compatibility; internal struct fields use Portuguese naming. Add visual highlight for active split pane rendered as 4 border rectangles at z-order 4, configurable via new TOML fields in [navigation] section: highlight-active-split = true|false (default: false) active-split-color = [r, g, b, a] (default: blue accent) Add ConfiguracaoMenuContexto struct in rio-backend with serde defaults for future TOML customization (currently unused, cores hardcoded in renderer). Add rio/CHANGELOG.md in Keep a Changelog format. Test coverage: frontends/rioterm/src/renderer/context_menu.rs: 80.39% lines / 88.89% fns rio-backend/src/config/context_menu.rs: 94.57% lines / 100% fns Total: 829/829 tests passing, 0 failing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix
tty: not a tty / no such devicewarning seen on the first shell line when Rio is launched from the Flatpak build (Fedora 44, runtimeorg.freedesktop.Platform/x86_64/25.08).The existing
flatpak-spawnintegration inteletypewriter/src/unix/mod.rs(added in #1116 and earlier work referenced in #198) successfully launches the host shell, but the PTY itself is still allocated inside the sandbox viaopenpty(). Bash login init scripts that callttyname(0)— most notably/etc/profile.d/gnupg2.sh(export GPG_TTY=$(tty)) on Fedora — therefore fail withENODEV, because the sandbox/dev/pts/Ndoes not exist in the host's mount namespace.GPG_TTYends up empty as a side effect.This PR introduces a small helper binary,
rio-pty-host, that runs on the host and creates the PTY there. Rio then spawns the user's shell through that helper, sottyname()resolves correctly andGPG_TTYis populated as expected.Approach
rio-pty-host(added to the workspace) — uses onlylibc(workspace) plusthiserror = \"2.0.1\"(promoted to[workspace.dependencies]). No additional transitive dependencies.openpty→fork→ child runssetsid+ioctl(TIOCSCTTY)+dup2+execvp→ parent relays I/O between its stdio (the sandbox PTY slave that arrived throughflatpak-spawn) and the host PTY master.unsafeblocks carry a// SAFETY:comment explaining the maintained invariant.starts_with('/')) before being passed toexecvpto avoid PATH manipulation;CStringfailures map to a dedicatedShellInvalidovariant.static AtomicBool(noArc::into_rawleak); SIGCHLD wakes up the relay loop, after whichwaitpidreturns the child exit status.On the Rio side:
teletypewriter::unix::flatpakcaches the/.flatpak-infoprobe and the resolved path of~/.local/bin/rio-pty-hostviaOnceLock./app/bin/rio-pty-hostviaflatpak-spawn --hostusing a stdin pipe and an atomicmktemp→chmod +x→mv -fsequence (atomicity comes fromrename(2)on the same filesystem, so concurrent Rio instances are safe).create_pty_with_spawnnow prefers the helper when available and falls back to the existing direct-shell invocation when it isn't, emitting atracing::warnthat names the residual cosmetic limitation.\$SHELLretrieved viaflatpak-spawnis defensively trimmed and falls back to/bin/shif empty.Distribution Note
This PR adds the source crate and the runtime auto-install plumbing inside Rio. The Flathub manifest at
flathub/com.rioterm.Riowill need a follow-up to actually buildrio-pty-hostand ship it at/app/bin/rio-pty-host; the Rio code degrades gracefully (legacy behaviour with the warn message) if that binary is absent.Tests
rio-pty-host: 7 unit tests covering argv parsing,openptyvalidity, absolute-path enforcement (relative shell name and../fooboth rejected), and a happy-path spawn that runs/bin/echoand waits for it.teletypewriter: 3 unit tests around the new module — installation no-op when/app/bin/rio-pty-hostis absent,obter_home_hostdoesn't panic, and a documented#[ignore]-d Flatpak detection test (theOnceLockcannot be reset between tests in the same process; the recommended invocation is viaassert_cmdin a subprocess).Validation
Known Limitation (v1)
SIGWINCHis not yet propagated byrio-pty-hostto the child shell. The initialwinsizeis set from<COLS> <ROWS>arguments, but dynamic resize after Rio's window changes will not reach the host PTY. A v2 follow-up should monitorTIOCGWINSZon the helper's stdin and forward viaTIOCSWINSZto the host master.Test plan
cargo check/clippy/fmt --check/testcleanrio-pty-hostand confirm:tty: ttyname: .../not a ttyttyreturns/dev/pts/Nandecho \$GPG_TTYprints the same/dev/pts/Nand behave normally~/.local/bin/rio-pty-hostafter first installRelated