jueves, 18 de marzo de 2010

Elegía de un Proceso Distribuido

[Basado en una historia real de punto flotante.]

Advertencia: La historia descrita a continuación contiene texto computacional explícito. Se recomienda leerlo en compañía de un sysadmin experimentado.

(¡es broma! léanlo, por favor) :D

por: Romeo Sánchez

Él era un proceso como cualquier otro; bueno, no como cualquiera, sino uno de alta prioridad, privilegiado, siempre sirviendo a los demás. Ella era un proceso más sencillo que luego se convertiría en su cliente. Cuando la conoció, desde el primer handshake de TCP, fue amor a primera vista. Comenzaron a tratarse, aunque al principio el scheduler no los hacía coincidir (el de alta prioridad casi siempre estaba ocupado), así que decidieron citarse (válgame la redundancia) por rendezvous, es decir, en cada encuentro uno esperaba pacientemente hasta que el otro llegara. Su relación se dio, como todas las relaciones, con cambios de contexto entre el modo kernel y el modo usuario que rompían la monotonía. De vez en cuando uno sorprendía al otro con alguna llamada síncrona inesperada que le alegraba el día, o incluso algún mensaje asíncrono, aunque también tenían sus interrupciones de I/O como toda pareja de procesos.

Con el tiempo decidieron tener un subproceso. Era uno pequeño, ligero, nacido a partir de un fork() en un nuevo shell. Siempre fue tímido y con dificultad lo mostraba un ps -a, aunque en ocasiones se rebelaba y acaparaba al procesador, consiguiendo llamar la atención no sólo de su proceso padre, sino hasta del mismo root. Aún así tenía sus ratos buenos, y hacía todas sus tareas con múltiples hilos de ejecución, escuchando atentamente.

Sin embargo, a pesar de sus emotivos encuentros por rendezvous, comenzaron a tener problemas y a contender, discutir, por el uso de los recursos. Las interrupciones eran cada vez más frecuentes, y la competencia por ser el primero en tener acceso al recurso derivó en una race condition insoportable ya para ambos, al grado de llegar a cuestionar incluso a root, diciéndole: "¿por qué me permites ejecutarme? un `kill -9` sería lo mejor, ya no quiero vivir así". Esa era su elegía de día y de noche, pero sólo otros daemons como cron lo escuchaban en silencio sin poder hacer nada. Quizá si el programador, recordando el caso de la cena de filósofos o del barbero dormilón, hubiera establecido una exclusión mutua (un mutex, pues) en las secciones críticas, el problema se habría resuelto, pero al final, después de una larga lucha de contención por recursos, quedaron atrapados en un deadlock, un bloqueo mutuo, cada quien esperando que el otro cediera, pero sin ceder él mismo, arruinando la relación, la comunicación, la ejecución y la interacción.

El desenlace fue triste: un solo `kill -9` fulminante bastó para terminar con su sufrimiento. El nuevo problema es que el proceso hijo ahora es huérfano, y dada su rebeldía, ni siquiera init, el más sabio de todos los procesos, ha podido hacer algo por él. Es ahora un alma en pena, un zombie, condenado a pagar por los errores de sus padres y por los errores del programador llevando para siempre (o al menos hasta el próximo reboot) un estigma en cada ps -a: la vergüenza de ser <DEFUNCT>.

:wq!