Зомби-процесс в многопроцессорном демоне python - PullRequest
5 голосов
/ 21 июня 2011

После исследования демонов Python этот проход, казалось, был самым надежным: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

Теперь я пытаюсь реализовать пул рабочих в классе демона, который, как я считаю, работает (я не проверил код полностью), за исключением того, что в конце я получаю процесс зомби. Я прочитал, что мне нужно дождаться кода возврата от ребенка, но я пока не могу точно понять, как мне нужно это сделать.

Вот некоторые фрагменты кода:

def stop(self):
    ...
    try:
        while 1:
            self.pool.close()
            self.pool.join()
            os.kill(pid, SIGTERM)
            time.sleep(0.1)
    ...

Здесь я попробовал os.killpg и ряд os.wait методов, но без улучшения. Я также играл с closing / joining в пуле до и после os.kill. Этот цикл, как он есть, никогда не заканчивается, и как только он попадает в os.kill, я получаю процесс зомби. self.pool = Pool(processes=4) встречается в разделе __init__ демона. Из run(self), который освобождается после start(self), я позвоню self.pool.apply_async(self.runCmd, [cmd, 10], callback=self.logOutput). Тем не менее, я хотел бы рассмотреть этот процесс зомби, прежде чем смотреть на это.

Как правильно реализовать пул внутри демона, чтобы избежать этого процесса зомби?

1 Ответ

4 голосов
/ 22 июня 2011

Невозможно иметь 100% уверенность в ответе, не зная, что происходит в процессе дочернего процесса / демона, но подумайте, может ли это быть так.Поскольку у вас есть рабочие потоки в вашем дочернем процессе, вам действительно нужно встроить некоторую логику, чтобы присоединиться ко всем этим потокам, как только вы получите SIGTERM.В противном случае ваш процесс может не завершиться (и даже если это произойдет, вы не сможете выйти изящно).Для этого вам необходимо:

  • написать обработчик сигнала для использования в дочернем / демоническом процессе, который захватывает сигнал SIGTERM и запускает событие для вашего основного потока
  • установитьобработчик сигнала в главном потоке (очень важный) дочернего процесса / демона
  • обработчик событий для SIGTERM должен выдать инструкции останова ВСЕМ потокам дочернего процесса / процесса демона
  • все потоки должныjoin () ed, когда они будут выполнены (если вы предполагали, что SIGTERM автоматически уничтожит все, что вам может понадобиться для реализации этой логики)
  • после того, как все соединено и очищено, вы можете выйти из основного потока

Если у вас есть потоки для ввода-вывода и всех видов вещей, тогда это будет настоящая рутина.

Кроме того, я обнаружил в ходе эксперимента, что особая стратегия для вашего слушателя событий имеет значениекогда вы используете обработчики сигналов.Например, если вы используете select.select (), вы должны использовать тайм-аут и повторить попытку, если тайм-аут произошел;в противном случае ваш обработчик сигнала не будет работать.Если у вас есть объект Queue.Queue для событий, и ваш прослушиватель событий вызывает его метод .get (), вы должны использовать тайм-аут, иначе ваш обработчик сигнала не будет работать.(«Реальный» обработчик сигналов, реализованный в C внутри ВМ, работает, но ваш обработчик сигналов Python не работает, если вы не используете тайм-ауты.)

Удачи!

...