Python 信号.SIGKILL 和多重处理

问题描述 投票:0回答:1

我正在尝试以任何方式在

Ctrl+C
之后返回提示。

我的应用程序使用线程执行器,以及带有线程的多进程。 当我尝试退出多进程队列时,出现 TypeError 问题。并且提示永远不会回来。

Traceback (most recent call last):
  File "/home/juanmf/projects/turret/env/lib/python3.11/site-packages/multiprocess/queues.py", line 248, in _feed
    obj = _ForkingPickler.dumps(obj)
...
  File "/home/juanmf/projects/turret/env/lib/python3.11/site-packages/dill/_dill.py", line 414, in save
    StockPickler.save(self, obj, save_persistent_id)
  File "/usr/lib/python3.11/pickle.py", line 578, in save
    rv = reduce(self.proto)
         ^^^^^^^^^^^^^^^^^^
TypeError: cannot pickle '_queue.SimpleQueue' object

我对修理泡菜 ATM 不太感兴趣。所以我只是尝试了硬核

SIGKILL
。 虽然我确实收到提示,但由于 RPi picamera 资源问题,我无法重新启动系统。被本应死亡的 python 进程占用。

Thread prints Dump Complete =======================================================

Killed
(env) juanmf@raspberrypi:~/projects/turret/src $ ps aux | grep pyth
root         956  0.0  0.4 102112 19256 ?        Ss   19:52   0:00 python /usr/sbin/wayvnc-control.py
juanmf      1100  0.0  0.8  63164 34052 ?        S    19:52   0:00 /usr/bin/python3 /usr/share/system-config-printer/applet.py
juanmf      2284  0.0  2.1 1185628 83564 pts/0   Sl   20:18   0:00 python3 Training.py
juanmf      2291  0.0  2.1 1251204 83280 pts/0   Sl   20:18   0:00 python3 Training.py
juanmf      2298  0.0  2.1 1316784 83304 pts/0   Sl   20:18   0:00 python3 Training.py

注意:我的应用程序有 mainProcess 和只有一个子子进程,所以我觉得很困惑,在杀死 Main 后,我仍然在

ps aux
输出中看到 3 个进程。
pgrep python3 | xargs kill -9
之后,我可以重新运行该应用程序。

令人讨厌的做法:


# Register the interrupt handler for the interrupt signal (Ctrl+C) or kill
signal.signal(signal.SIGINT, interrupt_handler)
signal.signal(signal.SIGTERM,  interrupt_handler)

...
def interrupt_handler(signum, frame):
    try:
        for process, proxyController in MultiProcessingControllerFactory.runningProcesses:
            print(process.pid, signal.SIGKILL)
            process.terminate()
            os.kill(process.pid, signal.SIGKILL)

        process = current_process()
        # exit the process
        if process._popen is not None:
            # Accessing protected because processing does not make any safety check here.
            process.terminate()

        GPIO.cleanup()
        flush_streams() // Prints buffered logs
        time.sleep(2)
    finally:
        os.kill(os.getpid(), signal.SIGKILL) // Kills this process.
        exit(0)

编辑:

我可以在单进程或多进程模式下运行我的应用程序。在多进程中,我只生成一个子进程(运行 Process.start() 的唯一方法会打印“SPAWNING!!”,并且我也只读取该输出一次)。 但如果我暂停 (

Ctrl+Z
) 应用程序并运行
ps aux | grep python
:

单声道进程输出

[1]+  Stopped                 python3 Training.py
(env) juanmf@raspberrypi:~/projects/turret/src $ ps aux | grep pyth
root         956  0.0  0.4 102112 19256 ?        Ss   19:52   0:00 python /usr/sbin/wayvnc-control.py
juanmf      1100  0.0  0.8  63164 34052 ?        S    19:52   0:00 /usr/bin/python3 /usr/share/system-config-printer/applet.py
juanmf      2078 43.0  3.6 1246880 142360 pts/0  TLl  20:12   0:06 python3 Training.py

多进程输出

[1]+  Stopped                 python3 Training.py
(env) juanmf@raspberrypi:~/projects/turret/src $ ps aux | grep pyth
root         956  0.0  0.4 102112 19256 ?        Ss   19:52   0:00 python /usr/sbin/wayvnc-control.py
juanmf      1100  0.0  0.8  63164 34052 ?        S    19:52   0:00 /usr/bin/python3 /usr/share/system-config-printer/applet.py
juanmf      2269 43.3  3.7 1468804 144136 pts/0  TLl  20:18   0:07 python3 Training.py
juanmf      2284  0.1  2.1 1185644 83564 pts/0   Tl   20:18   0:00 python3 Training.py
juanmf      2291  0.0  2.1 1251204 83280 pts/0   Tl   20:18   0:00 python3 Training.py
juanmf      2298  0.0  2.1 1316784 83304 pts/0   Tl   20:18   0:00 python3 Training.py
juanmf      2306  0.0  2.1 1464968 83636 pts/0   Tl   20:18   0:00 python3 Training.py

自杀退出后,看到3个进程。我猜是 MainProcess 和子进程死掉了。 (5 - 2 = 3) 这3个未注册的进程是从哪里来的? (此外,运行的 PID 是第一个和最后一个。)

python-3.x multithreading multiprocessing python-multiprocessing
1个回答
0
投票

由于某种原因,多进程队列的类型错误(在排队和腌制毒丸时或之后)阻止了

finally
块的运行。

  • 这三个额外的进程是由于
    m = Manager()
    调用(来自多进程)造成的,我将 id 包装在单例中并仅调用
    Manager()
    一次。然后在 exit_handler 处:
    if SharedManager.instance:
        SharedManager.getInstance().getManager().shutdown()

SharedManager 实现

exit(0) 关闭子进程工作后。除非您的应用程序出现 I/O 错误。我正在使用 sshkeyboard lib,第一次崩溃

Ctrl-C
,第二次退出提示,
os.kill()
不会发生这种情况。

© www.soinside.com 2019 - 2024. All rights reserved.