Tolerância a falhas

A BIF process_flag/2 pode ser usada para alterar o comportamento por omissão de um processo sempre que recebe um sinal EXIT, da seguinte forma:

process_flag(trap_exit,true)

Executar process_flag(trap_exit,true) altera o comportamento por omissão (terminar o processo) que vimos na aula anterior, transformando os sinais de EXIT em mensagens do tipo:

{'EXIT',Pid,Razão}

Um processo que execute a função process_flag(trap_exit,true) não termina automaticamente quando recebe um sinal EXIT doutro processo a que esteja ligado. Todos os sinais EXIT, incluindo aqueles em que a razão é o átomo normal são convertidos em mensagens. Estas podem ser recebidas e tratadas como qualquer outra mensagem.

Na figura seguinte o processo P1 está ligado a P2 e P2 está ligado a P3. Quando ocorre um erro em P1, um sinal  {'EXIT',PidP1,Razão} propaga-se a P2. No entanto, P2 executou process_flag(trap_exit,true), o que quer dizer que é capaz de converter o sinal numa mensage. Assim, o sinal EXIT não se propaga a P3.

Tratar sinais de EXIT
Fig. 1 - Tratamento e não propagação de um sinal EXIT


É sempre possível voltar ao comportamento por omissão executando process_flag(trap_exit,false).


Servidores robustos

Quando pretendemos construir um sistema robusto e tolerante a falhas uma boa opção é desenvolver o sistema por camadas. Cada camada apanha e corrige os erros da camada seguinte, tal como pode ser visto na figura seguinte:

Servidores em camadas

Exercícios

1) O servidor de recursos desenvolvido na aula anterior tem uma falha importante. E se um dos processos cliente que alocou um recurso morre enquanto detêm o recurso? Esse recurso nunca é libertado. Altere o exercício de forma a que se um processo morrer o recurso possa ser libertado.

2)  Desenvolva um sistema que modelize uma estrutura master-slave em que o master garanta que os slaves se mantêm "vivos":

As funções a desenvolver são: