domingo, 14 de diciembre de 2008

Recuperación automática de procesos erlang

La mayor ventaja que proporciona erlang es la gran potencia que tiene para la programación de procesos concurrentes.

Cuando se diseña software que va a ser programado en erlang suele dividirse el trabajo en múltiples procesos, además provee de mecanismos para comprobar fácilmente entre procesos si alguno se ha colgado y restaurarlo o ejecutar cualquier otra acción.

En el siguiente ejemplo.

-module(lib_misc).
-export([link_p/1, start/0, loop/0]).

start() ->
Pid = spawn(fun loop/0),
register(divisor, Pid),
spawn(lib_misc, link_p, [Pid]),
Pid.

loop() ->
receive
{A, B} ->
io:format("~nDivision: ~p", [A/B]),
loop()
end.


link_p(Pid) ->
process_flag(trap_exit, true),
link(Pid),
receive
{'EXIT', Pid, _} ->
NewPid = spawn_link(lib_misc, loop, []),
register(divisor, NewPid),
link_p(NewPid)
end.

Al compilar la librería y arrancarla se ejecutan dos procesos, el principal loop y otro llamado link_p.

El bucle principal simplemente recibe una tupla con dos números y los divide. Tiene al menos un error conocido y es que no comprueba cuando el divisor es cero.

El proceso link_p se enlaza al principal, la tarea de este proceso es esperar a que el principal se cuelgue (por ejemplo, división entre cero).
En el momento en el que el programa principal se ha colgado, recibe el mensaje de salida, restaura el proceso y se enlaza al nuevo.

Hay un detalle más, al iniciar un nuevo proceso el pid del antiguo no nos sirve para mandarle mensajes, así que se registra el átomo divisor para tener siempre una referencia global.

Registrar un nombre global estático no es la mejor solución, ya que no se pueden iniciar múltiples instancias del proceso divisor, debería ser un parámetro, lo he dejado así por que el ejemplo fuera más sencillo.

0 comentarios: