Quando um processo é concluído (seja porque ele sai ou é finalizado usando um sinal), todos os arquivos e conexões que ele mantém abertos são automaticamente fechados pelo sistema operacional. Não é fechado limpo, usando o protocolo MySQL para fechar conexões (supondo que haja um). É simplesmente descartado no nível TCP/IP e o servidor do outro lado apenas descobre que está falando com uma porta fechada. Isso nem sempre acontece instantaneamente, às vezes leva algum tempo até que o servidor perceba que o parceiro de discussão se foi. Quando isso acontece, ele considera que a conexão foi interrompida e limpa as coisas do seu lado.
Não abra a conexão MySQL no processo pai antes de usar
fork()
. fork()
duplica as estruturas de dados usadas para gerenciar o lado local da conexão e os resultados são imprevisíveis. Ainda mais, quando o filho conclui (não importa como), ele fecha a conexão (ou o SO a abandona), o servidor MySQL também fecha seu final e o processo pai descobre que não está falando com ninguém. Feche a conexão MySQL no processo pai antes de usar
fork()
em seguida, abra conexões separadas no processo pai e no processo filho, conforme necessário. Além disso, envolva qualquer comunicação MySQL com o servidor no processo pai entre:
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
e
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
Caso contrário, quando um processo filho for concluído, o processo pai será notificado com o
SIGCHLD
sinal. Um sinal recebido o retoma da suspensão (se for interrompido em um sleep()
ligue quando o sinal chegar). A biblioteca MySQL usa sleep()
como parte do protocolo MySQL para comunicação com o servidor. Se tal sleep()
retorna forçosamente mais cedo do que deveria (por causa de um sinal recebido), a biblioteca MySQL fica confusa e acaba relatando erros estranhos (como "o servidor MySQL sumiu") que na verdade não estão corretos. Dê uma olhada esta resposta para uma explicação detalhada.