tawasuyu

sergio/takana

> Una distribución Linux construida con un laboratorio funcional y hermético en el > sótano, y una terminal mutable, clásica y anárquica en el piso de arriba — diseñada > desde el suelo para que una IA programadora entienda, modifique y co…

TOML 1572Shell 203Rust 109Markdown 993728 Definiciones

gnome: 🏔 EL COMPOSITOR SUBE ENTERO SOBRE DRM REAL — cae el muro de input

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) <noreply@anthropic.com>

b01fad94e5786c8ef9cd90fa1fc4f7f88b90ea13 · por sergio · (hace 2 meses) · padre 03bdd41b4 · ver el árbol en este commit

Delta semántico

Ninguna definición cambió: el cambio es de texto, documentación o datos.

1 archivos · +79 −34

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.
+
+## CÓMO CAYÓ EL MURO ANTERIOR — la hebra de input (cerrado 2026-07-29)
+
+Vale la pena dejarlo escrito porque **el diagnóstico que había acá era falso** y la forma de
+refutarlo es reusable.
 
-**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.
+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]]).
 
-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`.
+**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.
 
-## LO QUE YA SE ARREGLÓ (dos bugs reales en arje-logind-compat)
+**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/<pid>/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.**
 
-Ambos encontrados arrancando esta imagen, ambos con test, ambos **locales todavía — falta
-commitear/pushear tawasuyu y re-pinear la receta**:
+**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 '<path>'» 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]]).