Когато даден процес завърши (или защото излиза, или е прекратен чрез сигнал), всички файлове и връзки, които поддържа отворени, се затварят автоматично от операционната система. Не се затваря чисто, чрез използване на MySQL протокола за затваряне на връзки (ако приемем, че има такава). Просто се изпуска на ниво TCP/IP и сървърът от другата страна просто открива, че говори със затворена врата. Това не винаги се случва моментално, понякога отнема известно време, докато сървърът забележи, че партньорът за дискусия е изчезнал. Когато това се случи, той счита връзката за прекъсната и изчиства нещата от своя страна.
Не отворете MySQL връзката в родителския процес, преди да използвате fork()
. fork()
дублира структурите от данни, използвани за управление на локалната страна на връзката и резултатите са непредвидими. Още повече, когато детето завърши (без значение как), то затваря връзката (или операционната система я прекъсва), MySQL сървърът също затваря своя край и родителският процес открива, че не говори с никого.
Затворете MySQL връзката в родителския процес, преди да използвате fork()
след това отворете отделни връзки в родителския и в дъщерния процес, ако е необходимо.
Освен това обвийте всяка комуникация на MySQL със сървъра в родителския процес между:
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD));
и
pcntl_sigprocmask(SIG_UNBLOCK, array(SIGCHLD));
В противен случай, когато дъщерен процес завърши, родителският процес се уведомява с SIGCHLD
сигнал. Полученият сигнал го връща от спящ режим (ако случайно е бил спрян в sleep()
обадете се, когато сигналът пристигне). MySQL библиотеката използва sleep()
като част от MySQL протокола за комуникация със сървъра. Ако такъв sleep()
принудително се връща по-рано, отколкото трябва (поради получен сигнал), MySQL библиотеката се обърква и в крайна сметка отчита странни грешки (като „MySQL сървърът е изчезнал“), които всъщност не са правилни.
Разгледайте този отговор за подробно обяснение.