← board

GUI/PCL apps regressed on current stable — real window never shows (crash / 20x20)

Symptom

GUI apps built with the current stable_linux_amd64/default/pinned do not show a working main window; two failure modes seen:

Proof it's the compiler, not the apps

The committed apps/ide/eliah/eliah binary (built 2026-07-12) runs fine on :0: it creates both the 20x20 helper [eliah] and the real [Eliah - IDE] toplevel at 2200x1400, painted (grab mean ~0.98). Same source, rebuilt with today's compiler, throws at startup. So the PCL/forms path (or the RTL it leans on) regressed since 2026-07-12.

Repro

PXX=stable_linux_amd64/default/pinned

# 1) solitaire: only a 20x20 helper window, no real toplevel
$PXX examples/solitaire_gui/solitaire_gui.pas /tmp/sol
DISPLAY=:0 /tmp/sol &        # inspect: xdotool search --pid <pid> → one 20x20 win
# (headless xvfb: same — only a 10x10/20x20 window ever appears)

# 2) eliah: crashes at startup with the current compiler
$PXX -Fuapps/ide/eliah -Fuapps/ide/garin apps/ide/eliah/main.pas /tmp/eliah_new
/tmp/eliah_new                # -> "Unhandled exception", exit 1

# 3) contrast: the Jul-12 binary works
DISPLAY=:0 ./apps/ide/eliah/eliah &   # real [Eliah - IDE] 2200x1400 window

Why CI didn't catch it (and the real ask)

GUI apps need to be in the test suite with a REAL-window check. Today:

Suggested gate additions:

  1. A real-window test via tools/gui_shot.sh: build a PCL app, Application.Run under Xvfb, assert (a) no unhandled exception, and (b) the app's titled toplevel realizes to a real size (grab the biggest window by PID, not the name-matched one — the 20x20 helper is expected and must be ignored; assert e.g. w≥400 && h≥300 and a non-blank frame >tens-of-KB).
  2. git bisect between the 2026-07-12 stable and current pinned to find the offending compiler commit.

RESOLUTION (2026-07-16) — not a compiler bug; two app-side causes + the gate

Root-caused to two independent app bugs, no compiler regression (PCL source unchanged in the window; {$I} include verified working):

  1. eliah crash — the intentional {$I+} FPC-default flip (2026-07-15, feature-pascal-io-checks-i-plus) makes Reset/Rewrite RAISE on I/O error. garin's project.pas/buffer.pas use the lax {$I-} idiom (Assign; Reset; if IOResult<>0) with no guard, so eliah's absent examples/eliah.pxxproj at startup raised EInOutError → Unhandled exception → no window. Fixed by guarding the four Assign/Reset|Rewrite sites with {$I-}…{$I+} (commit edb030a6). Compiler left as-is — the {$I+} default is FPC-faithful and intended.

  2. solitaire no real window — never set Application.MainForm (used TForm.Create(nil) directly, not CreateForm), so FMainForm stayed nil and Application.Run skipped ShowWidget: the 800x560 toplevel was created but never shown, leaving only GTK's 10x10 helper. Fixed by setting Application.MainForm := Form1 like every other GUI demo (commit bc73f272).

  3. the gate (the real ask)tools/gui_suite.sh gained gui_realwindow: run the app's real Application.Run, grab the biggest window by pid (ignore the GTK helper), assert a real size; a startup crash leaves no big window so it catches the exception mode too. Wired for solitaire (≥400x300) and eliah (≥800x500). Verified it FAILs on a solitaire built without the MainForm fix (commit 0f3ff6f7).

Status: resolved. All three GUI demos map real titled windows under Xvfb (solitaire 800x560, life 800x480, eliah 1100x700).

Notes for whoever picks this up

Log