[python] os.kill, послать ctrl-C дочернему процессу реально?
afaik, ctrl-c под виндой - это символ с кодом (лично не проверял)
http://svn.python.org/view/python/branches/release27-maint/L...
784 @unittest.skip("subprocesses aren't inheriting CTRL+C property")
785 def test_CTRL_C_EVENT(self):
чё делать?
# -*- encoding: utf-8 -*-
import signal
import os
import math
import sys
import subprocess
from time import sleep
def test_proc:
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGBREAK, signal_handler)
print '>>>>'
for i in xrange(10**2):
print '**'
for j in xrange(10**6):
a = math.sin(i)
print '>>>>'
def signal_handler(*args):
print 'signal', args
sys.exit(0)
def start_arbitr2(args):
pass
#start
args = ['python', args[0], 'subproc']
print args
pr = subprocess.Popen(args, stdin = subprocess.PIPE, stdout = None,
stderr = subprocess.STDOUT, startupinfo=None,
creationflags = subprocess.CREATE_NEW_PROCESS_GROUP)
sleep(0.5)
print 'killing'
pr.send_signal(signal.CTRL_C_EVENT)
print 'killed'
sleep(1)
print 'killing 3'
#pr.send_signal(signal.CTRL_C_EVENT)
pr.stdin.write(chr(3
pr.stdin.flush
print 'killed 3 '
sleep(5)
print 'killing 2'
pr.send_signal(signal.CTRL_BREAK_EVENT)
print 'killed 2'
if __name__ == '__main__':
print sys.argv
if len(sys.argv) > 1 and sys.argv[1] == 'subproc':
test_proc
else:
#start_arbitr
start_arbitr2(sys.argv)
вывод
F:\igor\apps\devel\python\subproc>python sigtest.py
['sigtest.py']
['python', 'sigtest.py', 'subproc']
['sigtest.py', 'subproc']
>>>>
**
killing
killed
**
**
killing 3
killed 3
**
**
**
**
**
**
**
**
**
killing 2
killed 2
http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
но хз как ты ее будешь из python-а вызывать
Можно, конечно, исхитриться и послать на консоль ctrl-c, но в управляющем окне проигнорировать или ещё какой костыль соорудить.
какой именно багофич?
http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
и
http://msdn.microsoft.com/en-us/library/ms684863%28v=vs.85%2...
Вот зачем они игнорируют ctrl-c ?
в питоне сделали обязательным флаг CREATE_NEW_PROCESS_GROUP для нового процесса, видимо, для того, чтобы симулировать получение сигнала только одним процессом.
Тут с картинками This signal cannot be generated for process groups. If dwProcessGroupId is nonzero, this function will succeed, but the CTRL+C signal will not be received by processes within the specified process group.
и
http://msdn.microsoft.com/en-us/library/ms684863%28v=vs.85%2...
If this flag is specified, CTRL+C signals will be disabled for all processes within the new process group.
Вот зачем они игнорируют ctrl-c ?
в питоне сделали обязательным флаг CREATE_NEW_PROCESS_GROUP для нового процесса, видимо, для того, чтобы симулировать получение сигнала только одним процессом.
скорее всего какую-нибудь свою функциональность через это протаскивали.
зы
более менее прямой путь получается: создается промежуточный процесс с new_process_group, который создает конечный процесс без new_process_group
когда надо промежуточный процесс посылает GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)
ззы
есть еще вариант - найти консольное окно, которое соответствует данному процессу, и послать ему ctrl-c
более менее прямой путь получается: создается промежуточный процесс с new_process_group, который создает конечный процесс без new_process_group
когда надо промежуточный процесс посылает GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)
тоже так думал делать,если ничего лучшего не придумать.
есть еще вариант - найти консольное окно, которое соответствует данному процессу, и послать ему ctrl-c
Это как? нет никаких проблем создать процесс в новом окне с CREATE_NEW_CONSOLE.
SetConsoleCtrlHandler(NULL, 0)
и теперь он уже ничего не игнорирует.
ура!
Это было в тесте ( тут но там они это делают в родительском процессе. Видать поэтому у них и не работает.
через FindWindow - это консольное окно можно найти
идея здесь, но реализована грязновато
http://stackoverflow.com/questions/2274668/how-to-send-keys-...
Ты, кстати, в курсе, что в венде и в юнихах сигналы работают принципиально разным образом — в юнихах вызывается хэндлер в том же треде, в венде — в отдельном? Ну, типа, ты вроде нашёл решение, но вдруг тебе это окажется полезным!
То, что я соорудил ещё и мультитредовое получилось? не критично конечно. Я им пользуюсь только для завершения, так что не очень критично, хотя и работает благодаря GIL, который вроде как не гарантирован.
Вроде threding.current_thread.ident у них одинаковый(у основного цикла и хендлера для сигнала) и выполнение останавливается, когда сигнал посылается.
Хотя processexplorer показывает ещё один
ntdll.dll!Rt|SetLastWin32ErrorAndNtStatusFromNtStatus+0x59 - это что такое?
PS. его кильнуть можно и всё продолжает работать.
Оставить комментарий
Phoenix
Есть некоторый сервер. Сервер слушает порты, что-то отправляет клиентам. Завершение работы проиходит по ctrl-C.Сейчас пишу для этого сервера тесты. Но никак не могу сэмулировать нажатие ctrl-C под виндой.
специально перешёл с 2.6 на 2.7, там появился os.kill для винды и специальные сигналы.
запускал дочерний процесс через multiprocessing и subprocess - ошибка одна и та же.
Если посылать какой угодно сигнал кроме CTRL_C_EVENT и CTRL_BREAK_EVENT - приложение помирает, не обработав сигнал.
Как работает subproc:
Как работает запускающий процесс: (killing - послали ctrl-C, killing2 - послали ctrl-break)
Заходим сюда и читаем
А в доке по Popen:
И как послать тогда CTRL_C_EVENT? и зачем он вообще тогда нужен, если он игнорируется в том слуае, когда указываешь флаг CREATE_NEW_PROCESS_GROUP, а когда не указываешь - его послать не дают с ошибкой