Подтвердить что ты не робот

Многопроцессный демона, не заканчивающийся на родительском выходе

У меня есть процесс многопроцессорности Python 2.7, который не будет выходить из родительского процесса. Я установил флаг демона, который должен заставить его выйти из родительской смерти. В документах указано, что:

"Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы".

p = Process(target=_serverLaunchHelper, args=args)
p.daemon = True
print p.daemon # prints True
p.start()

Когда я завершаю родительский процесс с помощью команды kill, демон остается в живых и работает (который блокирует порт при следующем запуске). Детский процесс запускает SimpleHttpServer и вызывает serve_forever, не делая ничего другого. Я предполагаю, что часть документов "попыток" означает, что процесс блокирующего сервера останавливает процесс смерти, и это позволяет процессу стать сиротой в результате. Я мог бы заставить ребенка нажимать на другой поток и проверять основной поток для изменения идентификатора родительского процесса, но это похоже на много кода, чтобы просто реплицировать функциональность демона.

Есть ли у кого-нибудь представление о том, почему флаг демона не работает, как описано? Это повторяется на 64-битной версии Windows8 и ubuntu12 32 бит vm.

Сжатая версия функции процесса ниже:

def _serverLaunchHelper(port)
    httpd = SocketServer.TCPServer(("", port), Handler)
    httpd.serve_forever()
4b9b3361

Ответ 1

Когда процесс завершается, он пытается завершить все свои демонические дочерние процессы.

Ключевым словом здесь являются "попытки". Кроме того, "выходы".

В зависимости от вашей платформы и реализации может быть, что единственный способ получить дочерние дочерние процессы - это сделать это явно. Если родительский процесс завершается нормально, он получает возможность сделать это явно, поэтому все в порядке. Но если родительский процесс прерывается резко, это не так.

В частности, для CPython, если вы посмотрите на источник, завершающие демонические процессы обрабатываются так же, как объединение не-демонических процессов: по ходьба active_children() в функции atexit. Таким образом, ваши демоны будут убиты тогда и только тогда, когда ваши обработчики atexit будут запущены. И, как говорится в этом модуле,

Примечание: функции, зарегистрированные через этот модуль, не вызывают, когда программа убивается сигналом, который не обрабатывается Python, когда обнаружена фатальная внутренняя ошибка Python или когда вызывается os._exit().

В зависимости от того, как вы убиваете родителя, вы можете обойти это, добавив обработчик сигнала, чтобы перехватить внезапное завершение. Но вы не можете, например, на POSIX, SIGKILL не перехватываться, поэтому, если вы kill -9 $PARENTPID, это не вариант.

Другой вариант - убить группу процессов, а не только родительский процесс. Например, если ваш родитель имеет PID 12345, kill -- -12345 в linux убьет его и всех его дочерних элементов (если вы не сделали ничего интересного).