When a process completes (either because it exits or it is terminated using a signal) all the files and connections it keeps open are automatically closed by the operating system. It is not closed clean, by using the MySQL protocol for closing connections (assuming there is one). It is simple dropped at the TCP/IP level and the server at the other side just discovers it is talking to a closed door. That doesn't always happen instantly, sometimes it takes some time until the server notices the discussion partner is gone. When this happens, it considers the connection as being dropped and cleans the things up on its side.
Do not open the MySQL connection in the parent process before using fork()
. fork()
duplicates the data structures used to manage the local side of the connection and the results are unpredictable. Even more, when the child completes (no matter how), it closes the connection (or the OS drops it), the MySQL server also closes its end and the parent process discovers it is talking to nobody.
Close the MySQL connection in the parent process before using fork()
then open separate connections in the parent and in the child process, as needed.
Also, wrap any MySQL communication with the server in the parent process between:
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
and
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
Otherwise, when a child process completes, the parent process is notified with the SIGCHLD
signal. A received signal resumes it from sleeping (if it happened to be stopped in a sleep()
call when the signal arrives). The MySQL library uses sleep()
as part of the MySQL protocol for communication with the server. If such a sleep()
forcibly returns earlier than it should (because of a received signal), the MySQL library gets confused and it ends up reporting strange errors (like "MySQL server is gone away") that are actually not correct.
Take a look at this answer for a detailed explanation.