Perl CGI темы
У меня возникла небольшая проблема с моим веб-приложением cgi, я использую ithreads для параллельной обработки, когда все потоки имеют общую "цель". Таким образом я отсоединяю их всех, и как только я нахожу свой ответ, я вызываю выход. Однако проблема заключается в том, что сценарий фактически продолжит обработку даже после того, как пользователь закрыл соединение и ушел, что, конечно, если проблема связана с ресурсами. Есть ли способ принудительно завершить работу родительского процесса, если пользователь отключился?
4 ответа
AFAIK создание и уничтожение потоков не является (по крайней мере, на данный момент) хорошей практикой Perl, потому что это постоянно увеличивает использование памяти!
Вы должны думать как-то иначе, чтобы выполнить работу. Обычно решение заключается в создании пула потоков и отправке аргументов с помощью общего массива или Thread:: Queue.
Если вы работаете под Apache, если клиент преждевременно закрывает соединение, он отправляет SIGTERM процессу cgi. В моем простом тестировании это убивает скрипт и потоки как поведение по умолчанию.
Однако, если есть прокси между сервером и клиентом, возможно, что Apache не сможет обнаружить закрытое соединение (так как соединение между сервером и прокси может оставаться открытым) - в этом случае вы отключены удачи
Я лично предложил бы изменить ваш подход, и при создании этих потоков для клиентского соединения, было бы сохранить и связать PID каждого потока с клиентским соединением. Мне лично нравится использовать демонов вместо потоков, т.е. Proc::Daemon. Когда клиент преждевременно отключается (до окончания потоков), отправьте SIGTERM каждому идентификатору процесса, связанному с этим клиентом.
Для корректного выхода переопределите подпрограмму завершения в процессе потока с условием остановки, что-то вроде:
$SIG{TERM} = sub { $continue = 0; };
Где $continue будет условием цикла обработки потока. Вам все равно придется остерегаться ошибок в коде, потому что даже вы можете попробовать переопределить $SIG{__DIE__}
, метод die() обычно не уважает это и умирает мгновенно без изящества;) (по крайней мере из моего опыта)
Я не уверен, как вы узнаете, отключился ли пользователь, но, если он есть, вам придется самим останавливать потоки, поскольку они, очевидно, не уничтожаются автоматически.
Уничтожение потоков - опасная операция, поэтому не существует хорошего способа сделать это.
Насколько мне известно, стандартным способом является наличие разделяемой переменной, которую потоки периодически проверяют, чтобы определить, должны ли они продолжать работать. Установите это значение, прежде чем выйти, и проверьте это значение в своих потоках.
Вы также можете отправить сигнал потокам, чтобы убить их. Документы знают об этом больше, чем я.