请设想一些子进程是由pcntl_fork()生成的,它们分别使用PDO打开mysql连接。 如果父进程将带有posix_kill()的SIGTERM信号发送到子进程,子进程将立即被终止。
所以,我对此有疑问。 当子进程终止时,它是否会自动关闭mysql连接? 或者我应该调用exit()函数吗?
我知道如果发送了SIGKILL,子进程会保持连接。 但是,我不知道SIGTERM的情况。
答案 0 :(得分:4)
当进程完成时(因为它退出或使用信号终止),操作系统会自动关闭它保持打开的所有文件和连接。通过使用MySQL协议关闭连接(假设有一个连接),它没有关闭。它在TCP / IP级别上很简单,而另一侧的服务器只是发现它正在关闭一扇门。这并不总是立即发生,有时需要一些时间,直到服务器注意到讨论伙伴已经消失。当发生这种情况时,它会认为连接被丢弃并清理它的一面。
在使用fork()
之前,不要在父进程中打开MySQL连接。 fork()
重复用于管理连接本地端的数据结构,结果是不可预测的。更重要的是,当孩子完成(无论如何),它关闭连接(或操作系统丢弃它),MySQL服务器也关闭它的结束,父进程发现它正在与任何人交谈。
在使用fork()
之前关闭父进程中的MySQL连接,然后根据需要在父进程和子进程中打开单独的连接。
此外,在父进程中将服务器的任何MySQL通信包装在:
之间pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
和
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
否则,当子进程完成时,将通过SIGCHLD
信号通知父进程。接收到的信号从休眠状态恢复(如果信号到达时恰好在sleep()
呼叫中停止)。 MySQL库使用sleep()
作为MySQL协议的一部分与服务器进行通信。如果这样的sleep()
强制返回的时间比它应该早(因为接收到的信号),MySQL库就会混淆,最终会报告实际上不正确的奇怪错误(比如“MySQL服务器已经消失”)。
请查看this answer以获取详细说明。
答案 1 :(得分:1)
SIGKILL从内存中删除进程而不进行任何清理。操作系统应清理所有打开的句柄,但可能会发生数据库连接以保持打开状态(至少在数据库通知死连接之前)。
不应该从应用程序中使用它,而只能从控制台中使用它作为最后的手段。
您应该使用SIGTERM或SIGINT,以便子进程正确退出并关闭所有打开的句柄。