Cuando se completa un proceso (ya sea porque finaliza o se termina con una señal), el sistema operativo cierra automáticamente todos los archivos y conexiones que mantiene abiertos. No se cierra limpio, utilizando el protocolo MySQL para cerrar conexiones (suponiendo que haya uno). Simplemente se cae en el nivel de TCP/IP y el servidor del otro lado simplemente descubre que está hablando con una puerta cerrada. Eso no siempre sucede instantáneamente, a veces toma algún tiempo hasta que el servidor se da cuenta de que el compañero de discusión se ha ido. Cuando esto sucede, considera que la conexión se ha interrumpido y limpia las cosas de su lado.
No abra la conexión MySQL en el proceso padre antes de usar fork()
. fork()
duplica las estructuras de datos utilizadas para administrar el lado local de la conexión y los resultados son impredecibles. Aún más, cuando el hijo completa (sin importar cómo), cierra la conexión (o el sistema operativo la interrumpe), el servidor MySQL también cierra su extremo y el proceso principal descubre que no está hablando con nadie.
Cierre la conexión MySQL en el proceso principal antes de usar fork()
luego abra conexiones separadas en el proceso principal y en el secundario, según sea necesario.
Además, ajuste cualquier comunicación de MySQL con el servidor en el proceso principal entre:
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
y
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
De lo contrario, cuando se completa un proceso secundario, se notifica al proceso principal con el SIGCHLD
señal. Una señal recibida lo reanuda de dormir (si se detuvo en un sleep()
llamar cuando llegue la señal). La biblioteca MySQL usa sleep()
como parte del protocolo MySQL para la comunicación con el servidor. Si tal sleep()
regresa a la fuerza antes de lo que debería (debido a una señal recibida), la biblioteca MySQL se confunde y termina informando errores extraños (como "El servidor MySQL se ha ido") que en realidad no son correctos.
Echa un vistazo a esta respuesta para una explicación detallada.