[python] os.kill, послать ctrl-C дочернему процессу реально?
afaik, ctrl-c под виндой - это символ с кодом (лично не проверял)
хм. кажись про это знают, судя по
http://svn.python.org/view/python/branches/release27-maint/L...
чё делать?
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
есть еще функция GenerateConsoleCtrlEvent
http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
но хз как ты ее будешь из python-а вызывать
http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
но хз как ты ее будешь из python-а вызывать
багофич растёт из виндовой GenerateConsoleCtrlEvent 
http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
Интересно, а зачем вот так сделали?

http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%2...
Интересно, а зачем вот так сделали?
Да вызвать не проблема. Она в os.kill и вызывается.Можно, конечно, исхитриться и послать на консоль ctrl-c, но в управляющем окне проигнорировать или ещё какой костыль соорудить.

>багофич растёт из виндовой GenerateConsoleCtrlEvent 
какой именно багофич?

какой именно багофич?
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 для нового процесса, видимо, для того, чтобы симулировать получение сигнала только одним процессом.
Тут с картинками http://stackoverflow.com/questions/1798771/send-ctrlc-to-sub...
>Вот зачем они игнорируют ctrl-c ?
скорее всего какую-нибудь свою функциональность через это протаскивали.
зы
более менее прямой путь получается: создается промежуточный процесс с 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
более менее прямой путь получается: создается промежуточный процесс с new_process_group, который создает конечный процесс без new_process_group
когда надо промежуточный процесс посылает GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)
тоже так думал делать,если ничего лучшего не придумать.
есть еще вариант - найти консольное окно, которое соответствует данному процессу, и послать ему ctrl-c
Это как? нет никаких проблем создать процесс в новом окне с CREATE_NEW_CONSOLE.
хехе. Нужно в дочернем процесс выполнить
и теперь он уже ничего не игнорирует.
ура!
Это было в тесте ( тут но там они это делают в родительском процессе. Видать поэтому у них и не работает.
SetConsoleCtrlHandler(NULL, 0)
и теперь он уже ничего не игнорирует.
ура!
Это было в тесте ( тут но там они это делают в родительском процессе. Видать поэтому у них и не работает.
>Это как? нет никаких проблем создать процесс в новом окне с CREATE_NEW_CONSOLE.
через FindWindow - это консольное окно можно найти
идея здесь, но реализована грязновато
http://stackoverflow.com/questions/2274668/how-to-send-keys-...
через FindWindow - это консольное окно можно найти
идея здесь, но реализована грязновато
http://stackoverflow.com/questions/2274668/how-to-send-keys-...
Ты, кстати, в курсе, что в венде и в юнихах сигналы работают принципиально разным образом — в юнихах вызывается хэндлер в том же треде, в венде — в отдельном? Ну, типа, ты вроде нашёл решение, но вдруг тебе это окажется полезным!
ты не про .net ?
То, что я соорудил ещё и мультитредовое получилось? не критично конечно. Я им пользуюсь только для завершения, так что не очень критично, хотя и работает благодаря GIL, который вроде как не гарантирован.
Вроде threding.current_thread.ident у них одинаковый(у основного цикла и хендлера для сигнала) и выполнение останавливается, когда сигнал посылается.
Хотя processexplorer показывает ещё один
ntdll.dll!Rt|SetLastWin32ErrorAndNtStatusFromNtStatus+0x59 - это что такое?
PS. его кильнуть можно и всё продолжает работать.
То, что я соорудил ещё и мультитредовое получилось? не критично конечно. Я им пользуюсь только для завершения, так что не очень критично, хотя и работает благодаря 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, а когда не указываешь - его послать не дают с ошибкой