Archivo por años: 2010

Devede y BT_FTP4Lxmedia

Acabo de lanzar una nueva versión de BT_FTP4lxmedia, el paquete con servidor FTP y cliente BitTorrent para los discos duros multimedia de MemUp. Como novedad, trae la versión 2.9 de BFTP y la 2.01 de Transmission.

También acabo de lanzar una miniactualización de Devede. Las novedades son, simplemente, mostrar el tipo de licencia en el diálogo Acerca de…, por petición de un certificador de instalaciones GNU/Linux (parece ser que es necesario que aparezca claramente la licencia), y añadir la traducción a húngaro. Nada excesivo, por lo que no hay necesidad de actualizarse a menos que se necesite alguna de las dos cosas.

Querida hacienda, dos puntos

Siempre ha sido la protagonista de las pesadillas de muchos contribuyentes, y fue, hasta hace poco, el atractor de toda la ira y odio del español medio (¡pero ya no! ¡ya hay entidades más odiadas que hacienda!). Sin embargo, hoy lanzaré una nota positiva sobre ella, porque cuando las cosas se hacen bien, es justo reconocerlo: este año, hacienda ha lanzado una versión del programa PADRE para Linux, poniendo fin a años de discriminación hacia los que tenemos tendencias informáticas minoritarias. ¡Y fijaos si está bien hecho que me ha salido a devolver!

Trabajando con señales

Estos días he seguido trasteando con Bftpd, y me puse a trabajar en resolver un problema bastante molesto: la cantidad de procesos zombie que deja tras de sí.

Para entender lo que pasa, primero hay que explicar que Bftpd lanza un nuevo proceso por cada nuevo usuario que se conecta, en lugar de utilizar un solo proceso para gestionar todas las conexiones. Así, tenemos un proceso padre que se limita a escuchar, y cada vez que llega una petición de conexión crea un proceso hijo para que la gestione; también comprueba cuando un hijo se muere (porque se haya cerrado la conexión).

Y aquí es de donde surge el problema: cada vez que un hijo termina, emite una señal (en concreto SIGCHLD) hacia el padre, el cual, al recibirla, ejecutará una pequeña función o callback y luego seguirá su ejecución normal. En el caso de Bftpd, dicho callback comprueba qué hijo es el que se ha muerto, pide su valor de retorno (para evitar que se quede zombie) y libera una serie de recursos que le reservó. En concreto, el código de dicha función comienza con un:

pid = wait(NULL);
[codigo para liberar los recursos del proceso PID]

Hasta aquí todo parece correcto; por desgracia, después de cada sesión con Bftpd quedaban varios procesos zombie. La razón era, obviamente, que el proceso padre no había leído su valor de retorno, por lo que el sistema operativo no los podía hacer desaparecer; sin embargo, en el callback se lee siempre dicho valor, así que es obvio que algo raro estaba pasando.

Para depurar el código empecé por añadir unos printfs: uno en el punto en que se crean los procesos hijo, mostrando su PID; otro en el punto de finalización de dichos hijos, y otro en la función de callback de SIGCHLD. Ejecuté el servidor, hice unas cuantas operaciones, vi la salida por pantalla, y… ¡Sorpresa! ¡Había menos llamadas a la función de callback que muertes! Si todo funcionase como se esperaba, el número debería ser exactamente el mismo (cada muerte debería emitir una señal SIGCHLD, la cual haría que se ejecutase el callback). Sin embargo, por alguna misteriosa razón, algunos procesos morían sin emitir la señal.

Para aquellos a los que les de igual el por qué, y simplemente necesiten saber el como, daré primero la solución: se trata de leer los PIDs de todos los hijos muertos en cada llamada al callback, en lugar de leer el de uno sólo. En otras palabras, el código del callback para SIGCHLD debe ser:

do {
        pid = waitpid(-1,NULL,WNOHANG);
        if (pid>0) {
            [codigo para liberar los recursos del proceso PID]
        }
} while (pid>0);

Vale, pero ¿por qué ocurre esto?

Para entender lo que ocurre hay que irse un poco a las profundidades del núcleo, porque se debe a un problema de cómo están implementadas las señales.

En Linux, cada proceso tiene un conjunto de bits, y cada uno representa una señal. Cuando un proceso quiere enviar una señal a otro, lo que hace realmente es poner a uno el bit de dicha señal en el proceso receptor.

¿Y cuando comprueba el receptor la llegada de una señal? En cada cambio de contexto: en un sistema operativo multitarea, los procesos se van turnando en el uso de la CPU, de manera que primero la usa unos milisegundos el proceso A, luego otros milisegundos el proceso B, y así sucesivamente hasta que se acaba la lista y se vuelve al proceso A. Cada vez que se cambia de un proceso al siguiente se realiza un cambio de contexto, en el que primero se guarda el estado del proceso actual, se busca quien será el siguiente proceso, se carga su estado y se le cede el control. Pero, y aquí está la cuestión, antes de este último paso se comprueba la máscara de bits de las señales, y si alguna está activa se ejecutará primero el callback correspondiente.

¿Y por qué se pierden entonces señales SIGCHLD? Pues porque dos o más procesos se mueren «a la vez»; esto es, se mueren dentro del mismo intervalo entre dos ejecuciones del proceso padre. Así, lo que ocurre es que cuando se muere el primero, pone a 1 el bit de la señal SIGCHLD del proceso padre; el repartidor de tareas, al ver que ha muerto, libera todo lo que puede y pasa al siguiente proceso; éste muere también, y también pone a 1 el bit de la señal SIGCHLD del proceso padre… pero ese bit ya estaba a uno, por lo que se queda como está. Finalmente, el repartidor decidirá que es el momento de ejecutar de nuevo el proceso padre, pero antes verá que el bit de la señal SIGCHLD está activo, por lo que lo pondrá a cero y  llamará al callback. El resultado: se murieron dos procesos pero sólo se ejecutó una vez la función asociada a la señal, por culpa de que las señales se almacenan con un único bit.

Es por esto que la solución indicada arriba funciona: la señal nos indica que se ha muerto AL MENOS un proceso hijo, así que debemos comprobar todos, y no asumir que cada uno enviará una señal.

Este caso nos demuestra que las señales son un sistema de comunicación bastante frágil, por lo que no se debe abusar de él. Cosas como «contar el número de veces que llega una señal» o similares pueden dar problemas incluso si hay un único emisor, porque si emite varias veces la misma señal antes de que el padre recupere el control de la CPU, contarán como una única señal. Y como muestra para los incrédulos, un pequeño programita que ejemplifica todo esto:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>

int v;

void senal(int valor) {

 printf("Recibidan");
 v++;
}

int main(int argc, char **argv) {

 int pid1,pid2,pid3,pid4,loop;

 v=0;
 signal(SIGUSR1,senal);
 pid1=getpid();
 pid2=fork();
 if(pid2==0) {
 fork();
 fork();
 printf("hijon");
 kill(pid1,SIGUSR1);
 kill(pid1,SIGUSR1);
 kill(pid1,SIGUSR1);
 kill(pid1,SIGUSR1);
 kill(pid1,SIGUSR1);
 sleep(2);
 } else {
 printf("padren");
 for(loop=0;loop<21;loop++) {
 sleep(1);
 }
 printf("Total: %dn",v);
 }
}

Este código crea un primer hijo, el cual se divide en cuatro hijos en total, y cada uno emite, de golpe, cinco señales SIGUSR1 al padre. Sin embargo, al ejecutarlo veremos que nunca se detectan todas ellas, sino, como mucho, una por proceso hijo (y a veces ni eso).

España es asín, o la chapuza de la TDT

Que en ¡Ejpaña! hacemos las cosas como las hacemos es bien sabido desde hace décadas. Pero ni con esas consigo acostumbrarme, oye.

Porque dejando de lado todo el tema de que sea ahora cuando, después de dos años de despliegue, se saquen de la manga la TDT de pago, con lo que la gente que quiera verla tendrá que tirar su deco y comprar uno nuevo con ranura para la tarjeta…

Porque dejando de lado que en unos meses saldrá la TDT de alta definición utilizando H.264, por lo que los decos y teles que se han comprado hasta ahora tampoco valdrán, porque sólo soportan MPEG-2…

Porque dejando de lado todas esas chapuzas que, dentro de lo que cabe, aún tienen una explicación lógica (que la gente gaste una y otra vez, dando más beneficios a los fabricantes de decos), lo que no consigo entender es quien fue el iluminado al que se le ocurrió programar el apagón analógico justo para mitad de la semana santa, cuando todos los comercios estarán cerrados, cuando no podrás llamar al antenista para que te corrija el problema de última hora, etc, etc, etc.

Señores políticos, que a estas alturas deberían saber perfectamente que aquí lo dejamos todo para el último momento.

¿Pero de qué me sorprendo? ¡Si a estas alturas soy YO quien debería saber perfectamente como son nuestros políticos!

Bftpd 2.7 para el LX Multimedia

Nueva versión del paquete ftp_bt4lxmedia, esta vez la 4.2, con la versión 2.7 de BFTPd. Las versiones anteriores enviaban un mensaje de error incorrecto al intentar borrar una carpeta con el comando de borrar archivos, lo que confundía al cliente FTP de Nautilus (el escritorio de Gnome) e impedía, por tanto, borrar carpetas desde él. La nueva versión ya permite borrarlas casi sin problemas.

Y digo casi porque, haciendo pruebas, surgió otro problema, y es que el comando ls -la no devuelve los ficheros ocultos, lo que hace que, si en una carpeta hay alguno, de un error al intentar borrarla. Voy a echar un vistazo al código a ver si puedo enviar al autor otro parche que corrija este detalle.

El paquete se puede encontrar en mi web, en un nuevo apartado que hice en la sección Programas.

Transmission 1.92

Acabo de lanzar una revisión del paquete de mejoras para el disco duro multimedia MemUp LX media. El cambio es la actualización del cliente BitTorrent Transmission a la versión 1.92.

AVISO: a partir de aquí empiezo a tocar en el sistema operativo del disco duro multimedia, lo que significa que estas acciones sólo las deben realizar aquellos que sepan muy bien lo que hacen. Si alguien se carga su disco, será el único responsable.

Avisados estáis.

La instalación es igual que en versiones anteriores: basta con bajarse el fichero ftp_bt4lxmedia_4.1.tar.bz2 y actualizar los ficheros indicados.

Al igual que en versiones anteriores, los binarios contenidos en este paquete están enlazados estáticamente, por lo que funcionarán en cualquier sistema con procesador MIPSel.

Si ya habías instalado una versión igual o anterior a la 3.0 de ftp_bt4lxmedia, debes borrar el fichero /tmp/hdd/volumes/HDD1/BT/transmission_tmp/settings.json o editarlo para modificar el parámetro rpc-whitelist.

Como ya avisé en un mensaje anterior, aquellos que se decidan a probarlo deben limitar el cliente BitTorrent (sea el que sea) a no más de 300 o 400 KBytes/seg de bajada, porque si se recibe a más velocidad, el disco multimedia se satura y acaba colgándose.

Entradas anteriores:

Nos la meten doblada

Aprovechando el puente (como ya viene siendo habitual), el Gobierno ha aprobado sin cambios la Ley de Economía Sostenible, que incluye la infame «Ley Sinde» de cierre de páginas web. Ahora dicha ley pasará al Congreso, donde se deberían presentar enmiendas y se votaría. Recordemos que el PSOE, de quien surge la ley, tiene mayoría relativa con 169 escaños. Si se aprueba (por mayoría absoluta), pasaría al Senado, donde se propondrían nuevas enmiendas y se votaría de nuevo. Para ser aprobada necesitaría también mayoría absoluta. En estos momentos, en el Senado tiene mayoría relativa el PP, aunque hay gente que sospecha que no están por la labor de oponerse a esto.

Devede 3.16.6

Una nueva revisión con leves cambios. No corrige fallos graves, sino pequeños bug publicados en el bugzilla de Ubuntu, en concreto los bugs 371229 (la descripción del menú del lanzador no sigue las normas de Gnome), 371369 (la entrada de menú del lanzador no está traducida a italiano), 484420 (los botones de debajo de las listas de ficheros y de títulos no mantienen la misma apariencia que el resto de botones) y 496740 (al pulsar ENTER en las propiedades de un título, debería actuar igual que al pulsar el botón Aceptar; lo he extendido al diálogo de comenzar la conversión).

FBZX para 32 y 64 bits

Lo prometido es deuda, por eso acabo de subir la versión 2.4.1 de FBZX que corrige un pequeño detalle que podría hacer que en arquitecturas de 64 bits Big-Endian no funcione correctamente. Además, he subido paquetes .DEB tanto para arquitecturas de 32 como de 64 bits, con lo que confío en que en breve esté disponible en Ubuntu64 (a día de hoy no lo está).