2017-07-14 53 views
0

請想象一下,一些子進程是由pcntl_fork()生成的,它們分別使用PDO打開mysql連接。 如果父進程發送帶有posix_kill()的SIGTERM信號給子進程,子進程將立即被終止。當發送SIGTERM時,子進程關閉mysql連接嗎?

所以,我對此有疑問。 當子進程終止時,它是否也會自動關閉mysql連接? 還是應該調用exit()函數?

我知道子進程在發送SIGKILL時保持連接。 但是,我不知道SIGTERM的情況。

回答

2

當一個進程完成時(或者因爲它退出或者使用一個信號終止),操作系統會自動關閉它保持打開的所有文件和連接。它沒有關閉乾淨,通過使用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

SIGKILL在沒有任何清理的情況下從內存中刪除進程。 O/S應清理所有打開的句柄,但可能發生db連接以保持打開狀態(至少在數據庫發現連接斷開之前)。

它不應該從應用程序使用,但只能從控制檯作爲最後的手段。

您應該使用SIGTERM或SIGINT,以便子進程正常退出並關閉所有打開的句柄。