Skip to content

fix: session edge paths, non-well-formed locked rc.xml, fail-soft packaging#4

Open
DeBondor wants to merge 5 commits into
singularityos-lab:mainfrom
DeBondor:fix/session-and-packaging-edges
Open

fix: session edge paths, non-well-formed locked rc.xml, fail-soft packaging#4
DeBondor wants to merge 5 commits into
singularityos-lab:mainfrom
DeBondor:fix/session-and-packaging-edges

Conversation

@DeBondor

@DeBondor DeBondor commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Five independent fixes on top of eec8a89, all on edge paths that the happy
path never reaches. None of them changes install-and-first-boot behaviour.

I booted the nightly ISO in QEMU with OVMF and swtpm first, so the overlap with
your own path-and-signing rework is already resolved: the /home/mirko/...
defaults and the sibling-checkout resolution are yours, not duplicated here.
Install → firstboot → greeter → desktop all worked, and the only error on the
serial console was bluetooth.service: exited before acquiring bus name org.bluez on the live boot, which nothing here touches.

fix: drop the double hyphen from the labwc-locked rc.xml comment

labwc-locked/rc.xml is not well-formed XML on main. The comment block that
opens on line 2 runs to line 25, and line 21 mentions --serve inside it, which
XML forbids:

$ python3 -c "import xml.dom.minidom; xml.dom.minidom.parse('rootfs-overlay/usr/share/singularity/labwc-locked/rc.xml')"
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 21, column 59

The greeter came up fine in the nightly, so libxml2 is evidently recovering from
it, but that is not something to rely on. Reworded the prose so the file parses.

fix: keep the OOBE's runtime state out of the greeter's XDG_RUNTIME_DIR

atom-oobe-session exports XDG_RUNTIME_DIR=/run/singularity for its own
compositor, which is the greeter's directory. Its runtime state then lands in a
directory owned by another user and, per the comment already in
singularity-session-common, a failed log open there is exactly the case that
leaks onto the seamless boot.

fix: reboot after the installer instead of leaving a bare compositor

sscommon_exec_labwc -s leaves labwc running after the startup command exits, so
after the installer's final "Restart now" button (which only closes the window)
the user is left looking at an empty compositor. -S terminates it with the
command. atom-installer-launch reboots on a finished install, so this only
matters on the give-up path.

Merged cleanly with the splash / DRM-master handoff you added to
atom-install-session in eec8a89.

build: do not abort packaging when fw-verify fails to build

[ -d "${ATOMLOOPS}/cmd/fw-verify" ] covers a checkout without that directory,
but not one where the directory exists and the build fails. Under set -e the
bare go build then aborts the whole run, after the erofs, the verity tree and
the UKI are already done. build-initramfs.sh already treats a missing verifier
as "base firmware only", so warn and carry on instead.

build: bump gsettings-desktop-schemas to 48.0 for accent-color

This one needs the most justification, because the nightly does not exhibit
it — see the last paragraph for why.

prepare.sh downloads Buildroot 2026.02.2, which ships
gsettings-desktop-schemas 45.0. Confirmed straight from the release tarball your
own script fetches:

$ curl -sO https://buildroot.org/downloads/buildroot-2026.02.2.tar.xz
$ tar xf buildroot-2026.02.2.tar.xz buildroot-2026.02.2/package/gsettings-desktop-schemas/
$ grep VERSION_MAJOR buildroot-2026.02.2/package/gsettings-desktop-schemas/gsettings-desktop-schemas.mk
GSETTINGS_DESKTOP_SCHEMAS_VERSION_MAJOR = 45
$ grep -c 'name="accent-color"' gsettings-desktop-schemas-45.0/schemas/org.gnome.desktop.interface.gschema.xml.in
0

accent-color landed in schemas 47. singularity-shell at the pinned
edab6504 writes it unconditionally on startup: src/core/main.vala:100
registers an Idle callback that calls update_accent_color(), which reads
dev.sinty.desktop accent-color. That defaults to 'blue' in
singularity-desktop at the pinned c7a6f3d4, a named colour, so the
"wallpaper-derived and custom colours have no named equivalent; skip syncing"
guard does not apply, and main.vala:883 runs:

try {
    var iface = new GLib.Settings("org.gnome.desktop.interface");
    iface.set_string("accent-color", color_name);
} catch (GLib.Error e) {

The catch cannot help: a key absent from the schema is a g_error inside GIO,
not a returned GError, so the process dies rather than raising. Reproduced
against a schema carrying the same id and no accent-color key, with the same
try/catch shape:

$ gsettings list-keys org.gnome.desktop.interface | grep -c accent-color
0
$ python3 -c 'from gi.repository import Gio
s = Gio.Settings.new("org.gnome.desktop.interface")
try:    s.set_string("accent-color", "blue")
except Exception as e: print("caught", e)'
GLib-GIO-ERROR **: Settings schema 'org.gnome.desktop.interface' does not contain a key named 'accent-color'
$ echo $?
134

134 is SIGABRT, and nothing was caught. So on a clean checkout
singularity-desktop dies on every shell start, the session supervisor gives up
and greetd falls back to the greeter: a login loop.

Why the nightly does not show this. Its image already ships schemas 48.0. I
carved the erofs out of sinty-os.iso and diffed the schema:

$ erofsfuse root.erofs mnt
$ grep -n 'name="accent-color"' mnt/usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml
314:    <key name="accent-color" enum="org.gnome.desktop.GDesktopAccentColor">
$ diff <(sed 's/^\s*//' mnt/usr/share/glib-2.0/schemas/org.gnome.desktop.interface.gschema.xml) \
       <(sed 's/^\s*//' gsettings-desktop-schemas-48.0/schemas/org.gnome.desktop.interface.gschema.xml.in) && echo identical
identical

It is byte-identical to the 48.0 tarball, and the image also carries
org.gnome.desktop.break-reminders and org.gnome.desktop.screen-time-limits,
both of which are absent from 45.0. Since nothing on main bumps the package,
that image was built against a buildroot-src that already carried the bump
rather than one prepare.sh produced from scratch — worth a look on its own,
because it means the nightly is not currently reproducible from a clean
checkout of eec8a89.

Written as buildroot-source-patches/0006-*.patch to match the patch set
eec8a89 introduced. Hashes are the upstream sha256sum file for 48.0.
Verified that it applies forward on a pristine 2026.02.2, that a reverse
dry-run is rejected there, and that the reverse dry-run succeeds on an
already-patched tree, so prepare.sh reports "already applied" on a rerun
instead of failing.

DeBondor added 5 commits July 26, 2026 13:04
The header comment mentioned singularity-shortcut's --serve mode. "--"
is not allowed inside an XML comment, so libxml2 fails the whole file
with "Double hyphen within comment" and labwc discards the locked
config: the greeter and OOBE compositor run with labwc defaults, without
the keybind lock this file exists to apply.
In client mode the OOBE runs as root and pointed XDG_RUNTIME_DIR at
/run/singularity purely to reach the persistent compositor's socket.
Every client library root loads then puts its runtime state there:
at-spi, dconf, gvfs and gvfsd land as root-owned 0700 directories, and
greeter-ready as root:root 0644, in a directory owned by the greeter
(0770 greeter:singularity-session) that the greeter has to write once we
hand over.

The greeter runs as uid greeter and cannot rewrite any of it, so it dies
on "can't create /run/singularity/greeter-ready: Permission denied" and
greetd loops on "greeter exited without creating a session": a black
screen after the OOBE completes.

Keep XDG_RUNTIME_DIR at root's own /run/user/0 and reach the compositor
through an absolute WAYLAND_DISPLAY, which libwayland uses verbatim
instead of resolving against XDG_RUNTIME_DIR. greeter-ready is the one
file that still has to be shared, so mark it with chmod as the own-labwc
fallback already does. The fallback starts its own labwc, which binds
its socket itself, so the inherited absolute path is unset there.
The installer's last page offers a button labelled "Restart now", but its
handler is only `this.close ()`. atom-install-session ran labwc with -s, so
the compositor outlived the window it was started for: the user pressed
"Restart now" and got a black screen with a cursor, with nothing left to
interact with and no way out short of a hard power cycle.

Make the exit path explicit in the launcher, which is the only place that
knows what should happen next:

  - atom-install drops /run/atom/install-complete. singularity-installer
    exits 0 both when the install finished and when the window was closed
    early, so exit status alone cannot tell the two apart.
  - atom-installer-launch stops exec'ing the installer and acts on its
    exit: reboot on a finished install (what the button promises), return
    on a finished OOBE (greetd moves on to the greeter), otherwise
    relaunch the wizard up to three times.
  - both session scripts run labwc with -S instead of -s, so the
    compositor terminates with the launcher and no clientless compositor
    is ever left on screen.

Verified on a live boot: the "is ready" page stays up until the button is
pressed, then the machine shuts down cleanly (stopping default.target,
sync, rebooting) and comes back into the OOBE on the installed disk.
The cmd/fw-verify guard covers an AtomLoops checkout that has no such
directory, but not one where the directory exists and the build fails
(a mid-refactor HEAD, a dependency it cannot resolve offline). Under
set -e the bare go build then aborts the whole run, after the erofs,
the verity tree and the UKI are already done.

build-initramfs.sh already treats a missing verifier as "no firmware
verifier, base firmware only", so this is a degraded image rather than
a broken build. Warn and carry on.
Buildroot 2026.02.2, which prepare.sh downloads, ships
gsettings-desktop-schemas 45.0, whose org.gnome.desktop.interface has no
accent-color key. That key landed in 47.

singularity-shell writes it unconditionally on startup. main.vala:100
registers an Idle callback that calls update_accent_color(), which reads
dev.sinty.desktop accent-color -- default 'blue', a named colour, so the
"skip wallpaper-derived and custom colours" guard does not apply -- and
then does, at main.vala:883:

    try {
        var iface = new GLib.Settings("org.gnome.desktop.interface");
        iface.set_string("accent-color", color_name);
    } catch (GLib.Error e) {

The catch cannot help. A key absent from the schema is a g_error inside
GIO, not a returned GError, so the process dies rather than raising:

    $ gsettings list-keys org.gnome.desktop.interface | grep -c accent-color
    0
    $ python3 -c 'from gi.repository import Gio
    s = Gio.Settings.new("org.gnome.desktop.interface")
    try:    s.set_string("accent-color", "blue")
    except Exception as e: print("caught", e)'
    GLib-GIO-ERROR **: Settings schema 'org.gnome.desktop.interface' does
    not contain a key named 'accent-color'
    $ echo $?
    134

134 is SIGABRT. singularity-desktop dies on every shell start, the
session supervisor gives up and greetd falls back to the greeter, which
is a login loop.

Written as buildroot-source-patches/0006-*.patch to match the patch set
eec8a89 introduced. Hashes are the upstream sha256sum file for 48.0.
Verified that it applies forward on a pristine 2026.02.2, that a reverse
dry-run is rejected there, and that the reverse dry-run succeeds on an
already-patched tree so prepare.sh reports "already applied" on a rerun.
@DeBondor
DeBondor force-pushed the fix/session-and-packaging-edges branch from 3eb450f to db373a1 Compare July 26, 2026 11:18
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.

1 participant