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.
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:
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: