Summary
On Linux, when any bundled gem is missing, GemCheck.verify! blocks for a full 120 seconds on a GUI dialog and then exits 1 having printed nothing to the terminal. Every CLI-only invocation is affected, including --help and --version, because the gem check runs at lich.rbw:39 — long before the CLI dispatcher is even loaded at lich.rbw:133.
The net effect from a terminal is that Lich appears to hang for two minutes and then do nothing, with no indication of why.
Reproduce
On a Linux box with zenity installed (any desktop distro), using a Ruby that doesn't yet have Lich's gems — e.g. right after following the 4.0.3 → 4.0.5 bump from #1529 with a fresh rbenv install:
ruby ~/code/dragonrealms/lich-5/lich.rbw --active-sessions
It sits for 120 seconds, prints nothing, exits 1. --help and --version behave identically. Interrupting shows where it is:
^C/home/user/code/dragonrealms/lich-5/lib/gemcheck.rb:541:in 'Process.wait': Interrupt
from lib/gemcheck.rb:541:in 'block in Lich::GemCheck.run_with_timeout'
from .../timeout.rb:306:in 'Timeout.timeout'
from lib/gemcheck.rb:541:in 'Lich::GemCheck.run_with_timeout'
from lib/gemcheck.rb:514:in 'Lich::GemCheck.alert_linux'
from lib/gemcheck.rb:295:in 'Lich::GemCheck.alert'
from lib/gemcheck.rb:73:in 'Lich::GemCheck.verify!'
from lich.rbw:39:in '<main>'
Cause
alert_linux (lib/gemcheck.rb:512-522) picks a GUI dialog whenever one is on PATH:
if cmd_available?('zenity')
run_with_timeout(['zenity', '--info', '--title', TITLE, '--text', body], ALERT_TIMEOUT_SECONDS)
elsif cmd_available?('kdialog')
...
else
warn "!!ALERT!! #{body}" # <-- the branch that would actually be visible
end
run_with_timeout spawns it with out: File::NULL, err: File::NULL and waits up to ALERT_TIMEOUT_SECONDS (120). So:
- The dialog may be on another workspace, behind other windows, or simply not rendering — the user launched from a terminal and isn't looking for one.
- Nothing reaches the terminal, because the message only ever goes into the dialog and the child's output is discarded.
- After 120s the child is TERMed and
verify! exits 1, still silently.
The information isn't lost, just never surfaced: alert calls write_log before opening the dialog, so TEMP_DIR/lich5-missing-gems.log already has the details. And the message it was trying to show is the actually-useful UNIX_MESSAGE — "You're missing required Ruby gems! Please run 'bundle install' from your Lich5 folder."
Why it bites harder than it looks
lich.rbw:39 runs GemCheck.verify! before lib/main/argv_options.rb is required at line 133. So the blocking dialog fires ahead of every early-exit CLI command — --help, --version, --active-sessions, --session-info, --link-to-sge, --install, and the rest. A user whose gems are missing cannot even run lich.rbw --help to find out what to do, which is exactly when they would.
Suggested fix
Prefer the terminal when there is one. alert_linux already has a perfectly good warn branch; it just isn't reachable when a dialog binary exists. Something like:
def alert_linux(body)
return warn("!!ALERT!! #{body}") if $stdout.isatty
# ... existing zenity/kdialog/xmessage chain
end
$stdout.isatty is already the established idiom for this in the codebase — lib/main/argv_options.rb uses it for --link-to-sge, --unlink-from-sge, and friends.
Options, roughly in order of preference:
- Use the
warn fallback whenever $stdout.isatty, so terminal launches get an instant readable error and desktop-launcher starts keep the dialog.
- Additionally, print the log path unconditionally before opening any dialog, so there is always a breadcrumb.
- Optionally drop
ALERT_TIMEOUT_SECONDS for the non-interactive case — two minutes is a long time to block a startup path that has already decided to exit 1.
Happy to put up a PR for (1) plus (2) if that's the direction you'd want.
Environment
- Linux,
zenity present
- Ruby 4.0.5 via rbenv (fresh install, gems not yet installed for it —
bundle install resolves the underlying missing-gem condition and is the correct user action; this issue is about the two-minute silent block that hides that fact)
Summary
On Linux, when any bundled gem is missing,
GemCheck.verify!blocks for a full 120 seconds on a GUI dialog and then exits1having printed nothing to the terminal. Every CLI-only invocation is affected, including--helpand--version, because the gem check runs atlich.rbw:39— long before the CLI dispatcher is even loaded atlich.rbw:133.The net effect from a terminal is that Lich appears to hang for two minutes and then do nothing, with no indication of why.
Reproduce
On a Linux box with
zenityinstalled (any desktop distro), using a Ruby that doesn't yet have Lich's gems — e.g. right after following the 4.0.3 → 4.0.5 bump from #1529 with a freshrbenv install:ruby ~/code/dragonrealms/lich-5/lich.rbw --active-sessionsIt sits for 120 seconds, prints nothing, exits 1.
--helpand--versionbehave identically. Interrupting shows where it is:Cause
alert_linux(lib/gemcheck.rb:512-522) picks a GUI dialog whenever one is onPATH:run_with_timeoutspawns it without: File::NULL, err: File::NULLand waits up toALERT_TIMEOUT_SECONDS(120). So:verify!exits 1, still silently.The information isn't lost, just never surfaced:
alertcallswrite_logbefore opening the dialog, soTEMP_DIR/lich5-missing-gems.logalready has the details. And the message it was trying to show is the actually-usefulUNIX_MESSAGE— "You're missing required Ruby gems! Please run 'bundle install' from your Lich5 folder."Why it bites harder than it looks
lich.rbw:39runsGemCheck.verify!beforelib/main/argv_options.rbis required at line 133. So the blocking dialog fires ahead of every early-exit CLI command —--help,--version,--active-sessions,--session-info,--link-to-sge,--install, and the rest. A user whose gems are missing cannot even runlich.rbw --helpto find out what to do, which is exactly when they would.Suggested fix
Prefer the terminal when there is one.
alert_linuxalready has a perfectly goodwarnbranch; it just isn't reachable when a dialog binary exists. Something like:$stdout.isattyis already the established idiom for this in the codebase —lib/main/argv_options.rbuses it for--link-to-sge,--unlink-from-sge, and friends.Options, roughly in order of preference:
warnfallback whenever$stdout.isatty, so terminal launches get an instant readable error and desktop-launcher starts keep the dialog.ALERT_TIMEOUT_SECONDSfor the non-interactive case — two minutes is a long time to block a startup path that has already decided to exit 1.Happy to put up a PR for (1) plus (2) if that's the direction you'd want.
Environment
zenitypresentbundle installresolves the underlying missing-gem condition and is the correct user action; this issue is about the two-minute silent block that hides that fact)