gnome: cae el SIGSEGV — el shell toma DRM master e input; muro nuevo en la hebra de input
Dos bugs REALES de arje-logind-compat, encontrados arrancando la imagen y
arreglados (con test) en el árbol de tawasuyu — todavía LOCALES, sin pushear:
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 sd_pid_get_session(), que
arje-sdlogin-compat resuelve LEYENDO /run/systemd/sessions. Huevo y gallina:
el estado en disco sólo se escribía después de un pedido que sólo ocurre si
el estado ya existe. Ahora se crea al arrancar (eager_session).
2. El object path de la Session estaba MAL ESCAPADO: era `/session/_1`. La
convención de systemd (bus_label_escape) codifica `_<hex>` todo lo que no sea
[A-Za-z0-9] **y también el primer carácter si es dígito** ⇒ el id "1" da
`_31`. Importa porque el cliente calcula el path por su cuenta y NO pregunta:
mutter reimplementa la misma regla en meta-dbus-utils.c. Con `_1` no había
nadie sirviendo ahí, la propiedad `Seat` volvía NULL y mutter —que no
chequea— moría de SIGSEGV en get_seat_proxy. Los objetos User NO usan este
escapado (systemd hardcodea `_<uid>`), así que user_path() queda igual.
Y ARJE_LOGIN_STATE=1 YA EXISTÍA: el comentario del daemon dice literalmente "en
arje (sin 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 era reinventar esa
perilla; queda de fallback inerte.
Resultado: el shell ya no crashea. Corre con 12 hilos, /dev/dri/card0 abierto
tres veces y /dev/input/event0 abierto — el TakeDevice de logind funciona y el
compositor tiene DRM master e input. Queda bloqueado en
meta_seat_impl_initable_init (meta-seat-impl.c:3154): espera en un condvar a que
la "Mutter Input Thread" avise que inicializó, y nunca avisa. Hipótesis principal
libudev-zero, que ya dio un episodio idéntico en el frente de la USB nvidia.
El gnome-start ahora le fuerza un core con SIGABRT al proceso colgado: sin gdb en
la imagen es la única forma de ver dónde está parado.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# Runbook — arrancar gnome-shell en QEMU (y dónde está el muro hoy)
|
||||
|
||||
Estado al 2026-07-29: **gnome-shell arranca, toma el rol de display server Wayland y muere de
|
||||
SIGSEGV en `meta_launcher_new`**. La causa está localizada con precisión (ver abajo); no es un
|
||||
misterio pendiente de diagnosticar, es una pieza de arje que falta implementar.
|
||||
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.
|
||||
|
||||
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
|
||||
@@ -35,59 +36,65 @@ 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 — y por qué no es un bug de mutter que haya que rodear
|
||||
## EL MURO DE HOY — la hebra de input de mutter
|
||||
|
||||
```
|
||||
#4 g_variant_get (value=0x0, format_string="(s&o)") ← GVariant NULO
|
||||
#5 get_seat_proxy (...) at src/backends/meta-launcher.c:407
|
||||
#6 meta_launcher_new (flags=META_LAUNCHER_FLAG_TAKE_CONTROL) at meta-launcher.c:464
|
||||
...
|
||||
#15 main () at src/main.c:664
|
||||
#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
|
||||
```
|
||||
|
||||
Mutter pide la propiedad `Seat` del objeto **Session** de logind — el `(s&o)` es la firma estándar
|
||||
de esa propiedad: `(nombre_del_seat, object_path_del_seat)`. `arje-logind-compat` adquiere
|
||||
`org.freedesktop.login1` y sirve el **Manager**, pero no expone un objeto Session con esa propiedad,
|
||||
así que la lectura devuelve NULL. Mutter no chequea y desreferencia ⇒ SIGSEGV.
|
||||
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.
|
||||
|
||||
Que mutter no valide es una fragilidad suya, pero **el hueco es nuestro**: falta el objeto Session.
|
||||
**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.
|
||||
|
||||
### La cadena completa que hubo que armar para llegar hasta acá
|
||||
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`.
|
||||
|
||||
Cada eslabón se descubrió arrancando la imagen, y ninguno estaba anotado antes:
|
||||
## LO QUE YA SE ARREGLÓ (dos bugs reales en arje-logind-compat)
|
||||
|
||||
1. **`gschemas.compiled` no existe.** meson NO lo genera cuando `DESTDIR` está seteado (lo dice en
|
||||
el log del build: *"Skipping custom install script because DESTDIR is set"*). Sin él GSettings
|
||||
aborta en el primer `g_settings_new()`. Se compila en el primer arranque.
|
||||
2. **`GI_TYPELIB_PATH` con `/usr/lib/gnome-shell`.** St/Shell/Gvc/Shew se instalan APARTE de
|
||||
`/usr/lib/girepository-1.0` porque son privados del shell. Es el env que no tiene análogo en KDE.
|
||||
3. **`/var/run` no existía.** `arje-logind-compat` busca el bus en la ruta legacy
|
||||
`/var/run/dbus/system_bus_socket`; sin el symlink reporta `bus_present=false` y se va a modo idle.
|
||||
4. **Política D-Bus de `login1` ausente.** `system.conf` trae `<deny own="*"/>`; normalmente systemd
|
||||
instala el fichero de política del servicio. Acá no hay systemd y el artefacto de
|
||||
arje-logind-compat es sólo el binario ⇒ hubo que escribirla. **Pertenece al artefacto de arje,
|
||||
no a la imagen**; está en el script de imagen sólo para que se vea qué falta empaquetar.
|
||||
5. **`/run/systemd/{sessions,seats,users}` vacíos.** `libelogind` (arje-sdlogin-compat) resuelve la
|
||||
C-ABI sd-login LEYENDO esos ficheros, y nadie los escribe: el `Announce` de arje-logind-compat al
|
||||
bus del fractal falla con `identity mismatch`, así que nunca hay sesión registrada. El
|
||||
`gnome-start` los escribe A MANO — **eso es ANDAMIO, y está marcado como tal en el script**. Con
|
||||
ese puente desaparece el `Failed to setup: Failed to find any matching session`.
|
||||
6. **Y entonces aparece el muro real**: el objeto Session de D-Bus (arriba).
|
||||
Ambos encontrados arrancando esta imagen, ambos con test, ambos **locales todavía — falta
|
||||
commitear/pushear tawasuyu y re-pinear la receta**:
|
||||
|
||||
### Gotcha de diagnóstico que costó una iteración
|
||||
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
|
||||
`sd_pid_get_session()`, que arje-sdlogin-compat resuelve LEYENDO `/run/systemd/sessions`. Huevo y
|
||||
gallina — el estado en disco sólo se escribía después de un pedido que sólo ocurre si el estado
|
||||
ya existe. Ahora la sesión se crea al arrancar (`eager_session`, apagable con
|
||||
`ARJE_LOGIN_EAGER=0`, uid por `ARJE_LOGIN_UID`).
|
||||
2. **El object path de la Session estaba mal escapado.** Era `/session/_1`; la convención de systemd
|
||||
(`bus_label_escape`) codifica como `_<hex>` todo lo que no sea `[A-Za-z0-9]` **y también el primer
|
||||
carácter si es dígito**, así que el id `"1"` da **`_31`**. Importa porque el cliente calcula el
|
||||
path por su cuenta y no pregunta: mutter reimplementa la misma regla en
|
||||
`meta-dbus-utils.c:escape_dbus_component`. Con `_1` no había nadie sirviendo ahí, la propiedad
|
||||
`Seat` volvía NULL y mutter —que no chequea— moría de **SIGSEGV en `get_seat_proxy`**. Los objetos
|
||||
`User` NO usan este escapado (systemd hardcodea `_<uid>`), así que `user_path()` queda igual.
|
||||
|
||||
`kill -0 <pid>` **tiene éxito sobre un ZOMBI** — el hijo existe como PID hasta que el padre lo
|
||||
cosecha, y el padre es el propio `gnome-start`, que sólo hace `wait` al final. La primera versión del
|
||||
script usaba `kill -0` y reportaba *"sin wayland-0 tras 45s"* cuando en realidad el shell había
|
||||
muerto en el primer segundo. Se mira el `State:` de `/proc/<pid>/status` (vacío o `Z` = muerto), y
|
||||
así sale el código real: **139 = SIGSEGV**.
|
||||
De paso, un arreglo de portabilidad musl preexistente: `libc::ioctl` toma `c_ulong` en glibc y
|
||||
`c_int` en musl, así que `DRM_IOCTL_SET_MASTER` se guarda pelado y se convierte en el sitio de uso.
|
||||
|
||||
**Y `ARJE_LOGIN_STATE=1` ya existía**: el comentario del daemon dice literalmente «en arje (sin
|
||||
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.
|
||||
|
||||
## Lo que falta, en orden
|
||||
|
||||
1. **Objeto Session en `arje-logind-compat`** con la propiedad `Seat` (y `TakeControl`/`TakeDevice`
|
||||
sobre él, que es lo que mutter llama enseguida para el DRM master). Esto destraba el arranque.
|
||||
2. **Que escriba `/run/systemd/{sessions,seats,users}`** en vez del puente a mano — y de paso
|
||||
arreglar el `identity mismatch` del Announce.
|
||||
3. **Empaquetar la política D-Bus** dentro del artefacto de arje-logind-compat.
|
||||
4. 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`).
|
||||
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`).
|
||||
|
||||
Reference in New Issue
Block a user