Bugs no en Xfce (2)

Hace más de seis meses escribí un artículo bastante largo llamado Bugs en Xfce (1) describiendo la busca y captura de un bug del que creía culpable un componente de Xfce, y que resultó ser un bug de gstreamer. El propio título sugería que iba a haber una segunda parte, que es la presente. Pero he decidido cambiarlo ligeramente porque, como en el anterior artículo, el bug que yo achacaba a un componente de Xfce ha terminado siendo (como ya entonces me temía) un bug de una parte diferente, mucho más profunda, de la pila Linux. Pero no ha sido hasta encontrar la solución cuando he podido confirmarlo.

El bug

Pero describamos el problema. Thunar, el file manager de Xfce, tiene un plugin llamado thunar-volman que nos muestra otras unidades o discos —particiones realmente—, y que nos sirve para montarlas y desmontarlas, etc. Cuando conectamos una nueva unidad como un USB stick o un disco externo nos la muestra en la lista de dispositivos para que podamos acceder a los mismos. Además se puede configurar para que monte automáticamente las nuevas unidades que se conecten (creo que es el comportamiento por defecto, aunque yo lo tengo deshabilitado).

Esta característica me estaba funcionando excepto cuando pinchaba mi teléfono Android en modo "USB mass storage" para pasarle o extraer ficheros. Buscando por Internet vi que otra gente tenía el mismo problema pero con CDs y DVDs. Probé a introducir un CD en mi CD-ROM y tampoco aparecía en Thunar. Supuse (acertadamente) que ambos problemas estaban relacionados.

Encontré un bug relacionado en el bugzilla de Xfce, pero por no abrirme una cuenta en un sitio más, reporté el bug a Debian: #721996. En un primer momento describía el bug como "no consistente", ya que algunas veces la unidad si se mostraba pero la mayoría de las veces no. Más tarde me percaté que el teléfono (o el CD) si aparecían en Thunar si el dispositivo estaba conectado (o el CD metido en la bandeja) antes de arrancar el sistema. Era después, cuando el sistema ya estaba en marcha, cuando las unidades no aparecían.

Podéis ver el intercambio de mensajes con el maintainer en el bug: a indicación suya miré si el dispositivo era detectado por los distintos niveles desde el hardware a thunar-volman (hardware → kernel → udev → udisks → dbus → thunar-volman). Aparentemente las notificaciones subían hasta llegar a udisks, después Thunar-volman se quejaba de errores en la consola (recogidos en el fichero .xsession-errors). El maintainer no volvió a decir nada y la cosa se quedó estancada.

Para mí en ese momento era claramente un problema de thunar-volman, entre otras razones porque si fuera un problema general, de una capa inferior, hubiera encontrado quejas de usuarios de otros escritorios como KDE, GNOME o Unity. Seguro que los usuarios de Ubuntu se hubieran quejado si los CDs no se vieran. Así que el problema debía estar en Xfce, que al ser un DE "minoritario" podía pasar desapercibido más fácilmente.

Esta idea cambió cuando encontré este post dándole cera a udisks2 y a su desarrollador. Con la mosca detrás de la oreja, hice una prueba: reiniciar el demonio de udisks2 teniendo el dispositivo conectado. ¡Funcionó! Así que era por eso que en el arranque detectaba los CDs y el teléfono: porque era cuando se lanzaba el demonio. Eso me proporcionaba al menos un workaround mientras lo arreglaban (si es que lo arreglaban, porque el catastrofismo de la crítica dejaba poco espacio a la esperanza). Eso sí, era un peñazo, porque el desarrollador ni se había tomado la molestia de incluir una forma de ordenarle al demonio que se reiniciase o forzar una actualización, y la gente de Debian tampoco (que seguro que tiene que ver con ser un servicio D-BUS). Cuando quería conectar el teléfono o leer un CD tenía que literalmente matar el proceso udisksd desde root y volver a lanzar el proceso a mano.

La solución

Revisando hace unos días el bug abierto, encontré referencias en el bugzilla de Xfce a estos otros dos bugs de Debian: #725978 (de udisks2) y #713877 (de udev). En estos bugs no sólo se describía el problema sino que se daban un par de soluciones.

El origen del problema se describe ahí como "udisks usa sondeo (polling) en espacio de usuario en vez de usar el interno del kernel", y las soluciones se basan en "activar el sondeo interno del kernel para los dispositivos de bloque". La primera solución hace eso literalmente, cambia el valor de cierta variable del kernel haciendo que el polling de dispositivos de bloque se efectúe cada 2000 milisegundos (u otro valor) en vez de 0 (desactivado):

echo 2000 > /sys/module/block/parameters/events_dfl_poll_msecs

Para hacer este cambio persistente, lo podemos añadir a /etc/rc.local para que el valor se cambie en cada arranque del kernel (otra alternativa es pasar un parámetro al kernel mediante grub).

Esta solución tiene un inconveniente, y es que es muy intrusiva: se aplica a todos los dispositivos de bloque, incluyendo los discos duros que en realidad no lo necesitan. Y como señala algún comentario "es una bomba de relojería bajo la alfombra" esperando a estallarnos en cualquier momento. ¿No podríamos restringirlo sólo a las unidades que se montan y desmontan, a las unidades removibles? Eso es lo que hace la segunda solución, mediante una regla de udev:

ACTION=="add", ATTR{removable}=="1", ATTR{events_poll_msecs}=="-1", ATTR{events_poll_msecs}="2000"

En cuanto a dónde poner esta regla, el parche de Ubuntu la introduce en el fichero 60-persistent-storage.rules, que en Debian está en el directorio /lib/udev/rules.d/. O puedes ponerla como aconsejan en /etc/udev/rules.d/61-removable-storage-polling.rules si no quieres que una actualización del paquete te la elimine. Pero en realidad, como la regla ya se ha introducido en el paquete udev a partir de la versión 204-9, deberías querer que se sobreescriba en la actualización siguiente.

Sólo hay un pequeño problema, y es que udev forma parte ahora del paquete systemd en Debian, y si no utilizas systemd init como sistema de arranque el paquete no se actualiza. Así que el bug está corregido, pero no para los que usamos sysvinit, que tendremos que introducir la regla a mano.

Activar el kernel polling no sólo sirve para este caso, sino que ayuda a otras aplicaciones que "no tienen dependencia del sondeo de espacio de usuario (udisks)" como el gestor de ficheros SpaceFM que también explica cómo activarlo.

¿Por qué ha tardado tanto este bug en ser corregido? Pues, primero, porque en algunas distros ya estaba corregido, como Ubuntu y derivados. Ubuntu lleva su propia versión de udev forkeada ya que no usaban systemd sino upstart. Gentoo usa su propio fork de udev, eudev.

Otra gente usaba todavía la antigua versión de udisks, la 1, en vez de udisks2. En udisks1 el sondeo lo hace la propia aplicación, mientras que udisks2 se reescribió para aprovechar las nueva característica de sondeo del kernel.
En Debian Wheezy, por ejemplo, el bug no existe porque emplea udisks1. Otra gente, ante los contínuos problemas con udisks2 se pasó a alternativas como udevil (del autor de la crítica a udisks2 de arriba y SpaceFM) o udiskie.

Los bugs existen y existirán probablemente siempre. Lo que no es de recibo es el tiempo que transcurre entre que se reportan y se solucionan, existiendo incluso soluciones. El bug #713877 es del 23 de junio de 2013, y ya venía incluso con la solución, y sin embargo no se ha cerrado (parcialmente) hasta el 26 de abril de 2014. Los que han abierto el bug contra udisks2 o como en mi caso contra un componente superior, ni siquiera nos enteramos. La información está dispersa en múltiples bugs, en múltiples bug trackers, ... No sé qué solucion hay, o si hay solución, pero en ocasiones el estado de estas cosas es desalentador.

:wq

blogroll

social