Skip to content

fix(qemu): heal libaio.so.1t64 soname on Arch/Fedora + skip sudo /etc/hosts spam (#40)#41

Merged
Benehiko merged 1 commit into
mainfrom
fix/libaio-soname-arch-40
Jul 18, 2026
Merged

fix(qemu): heal libaio.so.1t64 soname on Arch/Fedora + skip sudo /etc/hosts spam (#40)#41
Benehiko merged 1 commit into
mainfrom
fix/libaio-soname-arch-40

Conversation

@Benehiko

Copy link
Copy Markdown
Owner

Fixes #40.

Problem 1 — bundled QEMU fails to start on Arch/Fedora

After the v0.3.2 auto-update pulled a new bundled QEMU, vee start fails on Arch Linux:

qemu-system-x86_64: error while loading shared libraries: libaio.so.1t64: cannot open shared object file: No such file or directory

The vee-qemu bundle is built on a Debian-family host, so on Linux the binary's DT_NEEDED records the Debian 64-bit-time_t soname libaio.so.1t64. Distros that ship only the upstream libaio.so.1 (Arch, Fedora, …) can't satisfy it. On 64-bit architectures the ABI is identical — only the filename differs.

Fix (issue's suggested option 3, generalized)

  • New internal/qemubin/libcompat_linux.go reads the QEMU binary's DT_NEEDED entries via debug/elf. For any *t64 soname the host cannot resolve but whose un-suffixed variant exists, it creates an ABI-compatible compat symlink in ~/.vee/bin/ (e.g. libaio.so.1t64 -> /usr/lib/libaio.so.1). Generic to the whole Debian time_t transition, not hardcoded to libaio. No-op stub off Linux.
  • Wired into Ensure() on both the fresh-install path and the already-installed fast path, so existing broken installs self-heal on the next vee start.
  • The managed binary carries no rpath, so the compat symlink alone isn't enough — qemuEnv() now prepends the binary's directory to LD_LIBRARY_PATH on Linux at launch. darwin/windows inherit the parent env unchanged.

Problem 2 — /etc/hosts registration logs a sudo failure every boot

v0.3.2's post-boot hostname registration needs root and warned on every start when passwordless sudo wasn't available (non-fatal, VM still booted).

  • CanWriteHosts() probes for a writable /etc/hosts or passwordless sudo (sudo -n -v). The manager now skips registration with a single info-level log instead of attempting it and warning every boot.
  • removeHostsEntry short-circuits when the entry is already absent, so unregister on such hosts is a clean no-op.

Verification

End-to-end on an Arch host:

  1. Removed the manual workaround symlink → qemu-system-x86_64 --version fails with the exact issue error.
  2. Ran the healing path → ~/.vee/bin/libaio.so.1t64 -> /usr/lib/libaio.so.1 recreated.
  3. LD_LIBRARY_PATH=$HOME/.vee/bin qemu-system-x86_64 --versionQEMU emulator version 10.0.2, exit 0.

All three platforms cross-build (linux/darwin/windows), full test suite passes, golangci-lint clean, new unit tests added. Docs updated in docs/prerequisites.md (managed-QEMU compat note + hostname/sudo behavior).

🤖 Generated with Claude Code

…s spam (#40)

The bundled vee-qemu build is compiled on a Debian-family host, so on Linux
its DT_NEEDED records the Debian 64-bit-time_t soname `libaio.so.1t64`. Distros
that ship only the upstream `libaio.so.1` (Arch, Fedora, …) can't satisfy it,
so `vee start` failed with:

    error while loading shared libraries: libaio.so.1t64: cannot open shared
    object file: No such file or directory

The ABI is identical on 64-bit architectures — only the filename differs.

Fix (issue #40 suggested option 3): on Linux, qemubin now reads the QEMU
binary's DT_NEEDED entries and, for any `*t64` soname the host cannot resolve
but whose un-suffixed variant exists, creates an ABI-compatible compat symlink
in `~/.vee/bin/` (e.g. `libaio.so.1t64 -> /usr/lib/libaio.so.1`). This runs on
both fresh install and the already-installed fast path, so existing installs
self-heal on the next `vee start`. Because the managed binary has no rpath, the
QEMU launcher now also prepends the binary's directory to `LD_LIBRARY_PATH` on
Linux so the loader finds the compat symlink; darwin/windows keep inheriting the
parent env. The whole shim is Debian-transition-generic, not hardcoded to libaio.

Also fixes the secondary complaint: post-boot hostname registration now probes
for passwordless sudo (or a writable /etc/hosts) via `CanWriteHosts()` and skips
registration with a single info-level log instead of failing and warning on
every boot when sudo would prompt. `removeHostsEntry` short-circuits when the
entry is already absent so unregister on such hosts is a clean no-op.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Benehiko
Benehiko merged commit f725035 into main Jul 18, 2026
4 checks passed
@Benehiko
Benehiko deleted the fix/libaio-soname-arch-40 branch July 18, 2026 10:37
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

Successfully merging this pull request may close these issues.

v0.3.2 regression: bundled QEMU links libaio.so.1t64 (Debian soname), fails to start on Arch Linux

1 participant