From b01fad94e5786c8ef9cd90fa1fc4f7f88b90ea13 Mon Sep 17 00:00:00 2001 From: sergio Date: Wed, 29 Jul 2026 11:23:06 -0400 Subject: [PATCH] =?UTF-8?q?gnome:=20=F0=9F=8F=94=20EL=20COMPOSITOR=20SUBE?= =?UTF-8?q?=20ENTERO=20SOBRE=20DRM=20REAL=20=E2=80=94=20cae=20el=20muro=20?= =?UTF-8?q?de=20input?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Con el `O_NONBLOCK` de TakeDevice (tawasuyu 3dd88f582, receta re-sellada b3:7ffa9256), gnome-shell arranca en QEMU sobre el backend nativo KMS, no headless: BACKEND: Opening and taking control of device file '/dev/input/event0' (y event2, event1) BACKEND: Realizing stage 'MetaStageNative' KMS: Plane 33 … primary for CRTC 37 · Plane 34 … cursor Using Wayland display name 'wayland-0' == gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server El muro gráfico que este runbook anunciaba como «el que viene después» NUNCA APARECIÓ: los fixes que pagó la campaña KDE y quedaron precargados en gnome-start-qemu.sh alcanzaron tal cual. mutter crea el renderer gbm y elige card0 como primaria sin quejarse. Queda un solo muro, y no es un cuelgue: el shell sale con código 1 en `Requiring AccountsService` — una dep de RUNTIME que la receta ya tiene medida símbolo por símbolo. El runbook además CORRIGE su propio diagnóstico anterior (culpaba a libudev-zero) y deja escrito cómo se refutó, que es lo reusable: una sonda que hace lo mismo que el código sospechado pero por otro camino, y /proc por hilo ANTES de abortar —porque gdb no desenrolla a través de musl y el core sólo da `?? ()`. Co-Authored-By: Claude Opus 5 (1M context) --- docs/runbooks/gnome-qemu-desktop.md | 113 +++++++++++++++++++--------- 1 file changed, 79 insertions(+), 34 deletions(-) diff --git a/docs/runbooks/gnome-qemu-desktop.md b/docs/runbooks/gnome-qemu-desktop.md index 9354c187..22736fc4 100644 --- a/docs/runbooks/gnome-qemu-desktop.md +++ b/docs/runbooks/gnome-qemu-desktop.md @@ -1,9 +1,21 @@ # Runbook — arrancar gnome-shell en QEMU (y dónde está el muro hoy) -Estado al 2026-07-29: **gnome-shell arranca, toma el DRM master y los dispositivos de input por -logind, y queda BLOQUEADO esperando que termine de inicializarse la hebra de input de mutter.** El -SIGSEGV que había antes está arreglado (dos bugs reales de `arje-logind-compat`, abajo). Nada de -esto es un misterio pendiente de diagnosticar: cada muro está localizado por backtrace. +Estado al 2026-07-29: **el compositor SUBE ENTERO sobre DRM real.** gnome-shell toma el DRM master +y los tres dispositivos de input por logind, realiza el stage `MetaStageNative`, asigna los planos +primario y de cursor, y expone `wayland-0`: + +``` +BACKEND: Opening and taking control of device file '/dev/input/event0' ← y event2, y event1 +BACKEND: Realizing stage 'MetaStageNative' +KMS: Plane 33 … primary for CRTC 37 · Plane 34 … cursor +Using Wayland display name 'wayland-0' +== gnome-qemu :: compositor OK (wayland-0) — el shell ES el display server +``` + +Lo único que queda para tener escritorio es la **capa JS**: el shell sale con código 1 en +`JS ERROR: Requiring AccountsService, version 1.0: Typelib file … not found`. Ya no hay ningún +cuelgue ni ningún SIGSEGV: los tres muros anteriores están cerrados, cada uno por medición y no por +conjetura. Hermano de [`kde-qemu-desktop.md`](kde-qemu-desktop.md), del que reusa el andamiaje: la base `work/metal-rootfs`, la inyección de mesa-llvmpipe/LLVM/musl, el truco del console-getty y el propio @@ -36,35 +48,63 @@ gdb -batch -q -ex "set sysroot $PWD/work/gnome-qemu-rootfs" \ -ex "core-file /tmp/core.gnome-shell" -ex "bt 25" work/gnome-qemu-rootfs/usr/bin/gnome-shell ``` -## EL MURO DE HOY — la hebra de input de mutter +## EL MURO DE HOY — el typelib de AccountsService ``` -#5 g_cond_wait glib/gthread.c:1686 -#7 meta_seat_impl_initable_init src/backends/native/meta-seat-impl.c:3154 -#8 meta_seat_native_constructed src/backends/native/meta-seat-native.c:146 -#12 meta_backend_native_create_default_seat -#14 init_clutter src/backends/meta-backend.c:1293 +Gjs-CRITICAL: JS ERROR: Error: Requiring AccountsService, version 1.0: + Typelib file for namespace 'AccountsService', version '1.0' not found +Execution of main.js threw exception → gnome-shell sale con código 1 ``` -El hilo principal arranca la «Mutter Input Thread» y **espera en un condvar a que ésa avise que -terminó de inicializarse. Nunca avisa.** El proceso queda vivo e inmóvil: 12 hilos, `State: S`, -`wchan=futex_do_wait`, con `/dev/dri/card0` abierto TRES veces y `/dev/input/event0` abierto — o sea -que el `TakeDevice` de logind YA funciona y el compositor tiene DRM master e input. Lo que no cierra -es la inicialización del asiento de libinput. +No es un cuelgue: es una dep de RUNTIME que falta. La receta está escrita y medida en +`recipes/incoming-gnome/accountsservice.toml` y **no sella todavía** por dos huecos de NUESTRA capa +de compatibilidad, contados símbolo por símbolo en el comentario de esa receta: ocho símbolos +`sd-*` que `libelogind` no exporta (los cinco `sd_login_monitor_*` son una API de notificación, no +getters) y `fgetspent_r`, que es extensión de glibc y musl no tiene. -**Hipótesis principal, y no es nueva en este repo: `libudev-zero`.** `libinput_udev_assign_seat()` -enumera y monitorea por udev, y el rootfs no trae udev de verdad. Ya hubo un episodio idéntico en -otro frente —«input muerto = eudev pisó libudev-zero», ver [[mirada-usb-nvidia]]— así que el próximo -paso es mirar por ahí antes que en mutter. +## CÓMO CAYÓ EL MURO ANTERIOR — la hebra de input (cerrado 2026-07-29) -Para volver a sacar este backtrace: el `gnome-start` **le fuerza un core al proceso colgado con -SIGABRT** después del timeout (sin gdb en la imagen es la única forma de ver dónde está parado), y -lo deja en la raíz con `sync`. +Vale la pena dejarlo escrito porque **el diagnóstico que había acá era falso** y la forma de +refutarlo es reusable. -## LO QUE YA SE ARREGLÓ (dos bugs reales en arje-logind-compat) +Decía: «el hilo principal espera en un condvar a que la Mutter Input Thread avise que terminó de +inicializarse; nunca avisa» —eso era correcto— «hipótesis principal: `libudev-zero`, que +`libinput_udev_assign_seat()` enumera por udev y el rootfs no trae udev de verdad». Eso era la +conjetura, apoyada en un episodio parecido de otro frente ([[mirada-usb-nvidia]]). -Ambos encontrados arrancando esta imagen, ambos con test, ambos **locales todavía — falta -commitear/pushear tawasuyu y re-pinear la receta**: +**La sonda que la refutó**: `libinput list-devices`, que hace exactamente lo que hace +`init_libinput()` de mutter —`udev_new` + `libinput_udev_create_context` + +`libinput_udev_assign_seat("seat0")`—. Volvió con `rc=0` y los tres dispositivos listados. La +enumeración por /sys con libudev-zero funciona perfecto. Está horneada en `gnome-start` y corre en +cada arranque, antes del shell. + +**El dato que dio la causa**: `tid 201 [Mutter Input Th] wchan=evdev_read syscall=0`. El hilo estaba +dormido en un `read()` de evdev DENTRO DEL KERNEL. Ese volcado por hilo ya estaba en el script pero +corría *después* del `kill -ABRT`, sobre un `/proc//task` que ya no existía: salía vacío y no +decía nada. El core tampoco servía — gdb no desenrolla a través de musl y devuelve `?? ()` para los +11 hilos que no son el principal. **Acá `/proc` le gana al core.** + +**La causa**: `arje-logind-compat` abría el device de `TakeDevice` sin `O_NONBLOCK`. El compositor +no elige los flags —recibe el fd ya abierto por el bus—, y libinput asume no-bloqueante para poder +leer en bucle hasta `EAGAIN`; lo dice donde abre (`libinput/src/evdev.c:2401`) y le pasa +`O_RDWR|O_NONBLOCK|O_CLOEXEC` a `open_restricted()`, pero mutter, cuando hay logind, ignora esos +flags y delega la apertura. systemd-logind abre con `O_NONBLOCK`, así que la dependencia no se nota +hasta que la implementa otro. Arreglado en tawasuyu `3dd88f582`, con test. + +Y por qué la sonda no lo veía: `libinput list-devices` abre el devnode **él mismo**, con +`O_NONBLOCK`. Sólo el camino por logind pasaba por el fd malo. Esa asimetría es justamente lo que la +convirtió en un experimento y no en una repetición. + +Tres perillas de diagnóstico que quedaron y valen para el próximo muro: +`MUTTER_DEBUG` es una **lista de tópicos** (`g_parse_debug_string` sobre `meta_debug_keys`, +`src/core/util.c:42`), no un booleano — con `1` no encendía nada; con `backend` imprime +«Opening and taking control of device file ''» por cada device y dice en cuál se para. El ping +D-Bus a login1 separa «daemon tildado» de «daemon vivo que ya contestó». Y los logs de `/tmp` (tmpfs) +se copian a la raíz ext4 antes de abortar, para sacarlos con `debugfs` junto al core. + +## LO QUE YA SE ARREGLÓ ANTES (dos bugs reales en arje-logind-compat) + +Ambos encontrados arrancando esta imagen, ambos con test, ambos ya en tawasuyu y sellados: 1. **La sesión se creaba PEREZOSAMENTE.** `ensure_user` sólo corría dentro de un método del Manager, y `write_login_state` vive adentro. Pero mutter no empieza por D-Bus: lo primero que hace es @@ -87,14 +127,19 @@ De paso, un arreglo de portabilidad musl preexistente: `libc::ioctl` toma `c_ulo systemd) el launcher de sesión lo prende. Default off» — y el launcher es `gnome-start`. El puente que escribía `/run/systemd/` a mano fue reinventar esa perilla; queda como fallback inerte. +El muro gráfico que este runbook listaba como «el que viene después» **nunca apareció**: los fixes +que KDE dejó pagos y precargados en `gnome-start-qemu.sh` (`GBM_ALWAYS_SOFTWARE`, `kms_swrast`, +`LP_NUM_THREADS=1`, `MUTTER_DEBUG_SEND_KMS_MODIFIERS=0`) alcanzaron: mutter crea el renderer gbm y +elige `/dev/dri/card0` como primaria sin quejarse. Es el rédito directo de la campaña anterior. + ## Lo que falta, en orden -1. **La hebra de input de mutter** (el muro de hoy): mirar `libudev-zero` primero. -2. **Commitear y pushear tawasuyu** con los dos arreglos de arje-logind-compat, y re-pinear el - `commit` de `recipes/arje-logind-compat.toml` para sellar el artefacto de verdad. Hoy la imagen - corre un binario compilado a mano vía `ALC_BIN=`, que **no es reproducible**. -3. **Empaquetar la política D-Bus de login1** dentro del artefacto de arje-logind-compat. -4. Arreglar el `identity mismatch` del `Announce` al bus del fractal (hoy sólo un WARN). -5. Recién después: el muro gráfico (GBM/EGL software sobre virtio-gpu), donde KDE ya dejó los fixes - pagos y precargados en `gnome-start-qemu.sh` (`GBM_ALWAYS_SOFTWARE`, `kms_swrast`, - `LP_NUM_THREADS=1`, `MUTTER_DEBUG_SEND_KMS_MODIFIERS=0`). +1. **`AccountsService`** (el muro de hoy): cerrar los ocho símbolos `sd-*` en `arje-sdlogin-compat` + y `fgetspent_r`, sellar `accountsservice`, y hidratar su typelib. Ojo al costo: re-sellar + `libelogind` re-hashea todo lo que lo declara (mutter, gnome-shell, polkit…) ⇒ pasar + `yupana radio libelogind` ANTES de tocarlo. +2. **Empaquetar la política D-Bus de login1** dentro del artefacto de arje-logind-compat (hoy la + escribe el script de imagen). +3. Arreglar el `identity mismatch` del `Announce` al bus del fractal (hoy sólo un WARN). +4. Con la capa JS viva: validar CON PANTALLA (`DISP=gtk`), nunca sólo por serial — regla heredada de + KDE ([[metal-dual-desktop-en-curso]]).