Отправить сигнал / событие независимому процессу - PullRequest
0 голосов
/ 13 ноября 2018

Итак, у меня полностью независимый процесс с известным PID.

Я хочу послать ему какое-то прерывание от другого не связанного процесса, которое заставит его «изящно» завершиться.

В Linux это будет выглядеть примерно так:

first_script:

def signal_handler(signum, stack):
    print("SIGNAL RECIEVED")
    sys.exit()

signal.signal(signal.SIGUSR1, handle_signal)
while True:
    print("Im working")

Второй скрипт:

known_pid = input("Enter pid")
os.kill(int(known_pid), signal.SIGUSR1)

Поскольку Windows не поддерживает передачу сигналов таким образом, она, очевидно, не будет работать, но я не смог найти другое простое решение (после довольно обширных исследований).

Ответы [ 2 ]

0 голосов
/ 17 ноября 2018

Вы можете использовать Windows API в соответствии с pywin32 или взломать его с помощью сокета.

Решение для сокетов быстрое и грязное:

# waiting process

import socket
import select
import time

server = socket.socket()
server.bind(('localhost', 1337))
server.listen(5)

# this select() call returns ([server], [], [])
# if server is readable, else ([], [], []), and waits 0 seconds
while not select.select([server], [], [], 0)[0]:
    print('working')
    time.sleep(0.5)


# parent process

import socket    
socket.create_connection(('localhost', 1337))

Решение для Windows длиннее, но более точно представляет проблему:

# waiting process

import time
import win32event

# open an existing event by name with the required access
# (didn't work for me with EVENT_MODIFY_STATE, got "Access denied" error)
event = win32event.OpenEvent(win32event.EVENT_ALL_ACCESS, 0, "MY_NAME")

# Wait 0 seconds on the event. If event has been set, WAIT_OBJECT_0 is returned
while win32event.WaitForSingleObject(event, 0) != win32event.WAIT_OBJECT_0:
    print('working')
    time.sleep(0.5)


# parent process
# note that it should be run first

import win32event
import time

# create event by name
event = win32event.CreateEvent(
    None,       # not inherited by child processes
    False,      # auto-reset the event after it is set
    False,      # created unset
    "MY_NAME",  # event name
)
time.sleep(5)  # wait for waiting process to start
win32event.SetEvent(event)

Это только минимальный POC.Рекомендуется прочитать о объектах событий , чтобы найти точное решение, которое вам подходит.

0 голосов
/ 16 ноября 2018

Как насчет использования psutil , я думаю, что оно вполне подходит для вашего случая.

Как указано в документе , следующий код может сделать то, что вы хотите.Хотя вам может не понадобиться часть find_procs_by_name.

import os
import signal
import psutil

def find_procs_by_name(name):
    "Return a list of processes matching 'name'."
    ls = []
    for p in psutil.process_iter(attrs=["name", "exe", "cmdline"]):
        if name == p.info['name'] or \
                p.info['exe'] and os.path.basename(p.info['exe']) == name or \
                p.info['cmdline'] and p.info['cmdline'][0] == name:
            ls.append(p)
    return ls

def kill_proc_tree(pid, sig=signal.SIGTERM, include_parent=True,
                   timeout=None, on_terminate=None):
    """Kill a process tree (including grandchildren) with signal
    "sig" and return a (gone, still_alive) tuple.
    "on_terminate", if specified, is a callabck function which is
    called as soon as a child terminates.
    """
    if pid == os.getpid():
        raise RuntimeError("I refuse to kill myself")
    parent = psutil.Process(pid)
    children = parent.children(recursive=True)
    if include_parent:
        children.append(parent)
    for p in children:
        p.send_signal(sig)
    gone, alive = psutil.wait_procs(children, timeout=timeout,
                                    callback=on_terminate)
    return (gone, alive)

pid = find_procs_by_name('POWERPNT.EXE')[0].pid
print(find_procs_by_name('POWERPNT.EXE')[0].pid)
kill_proc_tree(pid)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...