Summary
On the glibc wasm32 machine, the mc binary in viewer mode (mcview FILE, i.e. mc -v) traps unconditionally on startup: RuntimeError: unreachable at g_locale_from_utf8, reached from a resumed (coroutinized) unix_error_string frame. The user-runtime then reports a hard invariant violation — set-over-set: parked slot not empty — a coroutinized frame tried to park while a previous park slot was still occupied, because the call chain reaching it passes through a native (non-coroutinizable) frame. The machine dies (blank screen).
The same binary in file-manager mode (mc) runs fine, so this is not a broken build of mc — it is a coroutinize-runtime limitation exposed by mcview's init path. It is the same class as the msort_r reason=vla refusal in #2: a function the plugin must coroutinize cannot legally park given the native frame on the live stack.
Environment
- Machine:
dmitry/linux-6.12-glibc-bash-coreutils(wasm32, glibc pool, dynamic-main). - mc: GNU Midnight Commander 4.8.33, built via the glibc overlay (BRINTOS-32).
- Reproduced in-browser on brintos.io (headless Chrome), 2026-07-10.
Reproduction
Unconditional — independent of the file's type or size:
printf 'alpha\nbeta\ngamma\n' > /tmp/t.txt
TERM=ansi exec /usr/bin/mcview /tmp/t.txt
(exec only because the site's forked children cannot read the tty — a separate kernel issue, linux#7 — unrelated to this trap.) Also reproduced on a 26-line rootfs file (/root/selftest_mc.sh). Every run: blank screen, machine halts.
Trap (browser console)
hardwarejs: user[1] ERROR: unreachable
RuntimeError: unreachable
at mc.g_locale_from_utf8 (wasm-function[836])
at mc.unix_error_string.resume (wasm-function[786])
at mc.hwjs_resume ... at mc.hwjs_drive_loop ... at mc._start
hwjs-user-rt VIOLATION: set-over-set: parked slot not empty at a new park
(a coroutinized frame parked under a NATIVE caller and the witness reached the next park)
Evidence localizing the trigger
Pointing MC_DATADIR at a writable, empty directory stops the crash:
mkdir -p /tmp/mc
MC_DATADIR=/tmp/mc TERM=ansi exec /usr/bin/mcview /tmp/t.txt # viewer opens, no trap
With MC_DATADIR pointed away from the installed tree (/usr/share/mc, /etc/mc), mcview skips loading those files (skin, syntax, charset, sfs.ini — the last is even warned missing) and falls back to its built-in skin; the trap does not fire. So the trap is provoked while mcview reads one of its data/config files from the read-only cloud rootfs during init (most likely the skin .ini, whose string handling reaches g_locale_from_utf8), on a stack that has already been coroutinized past a native frame.
This is not a usable workaround: with MC_DATADIR redirected there is no skin, and the built-in fallback renders unreadably (blank) under this terminal. It only localizes the fault to the coroutinize runtime, not the mc recipe.
unix_error_string (mc lib/util.c) formats an errno string and calls g_locale_from_utf8 to charset-convert it; g_locale_from_utf8 → g_convert → iconv, which yields. It is a legitimate coroutinizable function. The defect is that the runtime cannot honor the park when a native frame is interposed between it and its coroutine parent.
Suggested direction
Same as #2 — either teach the plugin/runtime to coroutinize/park correctly when a native frame is interposed (spill/relocate as needed), or give the charset-conversion path (g_convert/iconv) a non-yielding fast path so it does not require a park in this context (e.g. identity / small-buffer conversions). Until then any glibc app whose error/skin path reaches g_locale_from_utf8 on a coroutinized-under-native stack traps the same way.
No candidate fix attached: this is a toolchain (coroutinize) defect, not fixable in the mc build recipe; the MC_DATADIR observation degrades rendering and is diagnostic only.