multiprocessing 让子进程忽略信号,手动关闭子进程
2024-08-24 10:35:24
起因
同事想要写一个代码,主进程中监听SIGINT、SIGTERM信号退出,并关闭启动的子进程,代码类似这样
import signal
import sys
import time
from multiprocessing import Process
from multiprocessing import Manager
class Test:
def __init__(self):
self.is_running = True
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
signal.signal(signal.SIGTERM, self._signal_handler)
def _signal_handler(self, signum, frame):
"""
Terminate scenario ticking when receiving a signal interrupt
"""
self.is_running = False
print('关闭场景调度')
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
while running.value:
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
def run(self):
"""启动场景调度"""
kill_task_lst = Manager().list()
running = Manager().Value(bool, True)
print('启动监控进程')
p = Process(target=self.listen_manage, args=(running, kill_task_lst, ))
p.start()
while self.is_running:
time.sleep(0.5)
print("main is running")
但是发现在ctrl + c 时候,子进程也同时接收到了信号,退出了
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
Process Process-3:
Traceback (most recent call last):
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "D:\python_projects\pythonProject\test_egg\test.py", line 35, in listen_manage
time.sleep(1)
KeyboardInterrupt
main is running
这时猜想到可能是子进程也监听了SIGINT,退出了程序,所以想在子任务中设置忽略信号,改造后的 listen_manage:
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while running.value::
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
运行后会报 BrokenPipeError: [WinError 232] 管道正在被关闭。
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
main is running
child is running
Process Process-4:
Traceback (most recent call last):
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 315, in _bootstrap
self.run()
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "D:\python_projects\pythonProject\test_egg\test.py", line 37, in listen_manage
kill_task_lst.append(1)
File "<string>", line 2, in append
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\managers.py", line 834, in _callmethod
conn.send((self._id, methodname, args, kwds))
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\connection.py", line 206, in send
self._send_bytes(_ForkingPickler.dumps(obj))
File "D:\software\anaconda\envs\test_egg1\lib\multiprocessing\connection.py", line 280, in _send_bytes
ov, err = _winapi.WriteFile(self._handle, buf, overlapped=True)
BrokenPipeError: [WinError 232] 管道正在被关闭。
这里想到的原因是父进程直接退出了,导致共享变量kill_task_lst被关闭导致的,所以想在关闭管道前等待子进程退出
可执行的完整代码:
import signal
import sys
import time
from multiprocessing import Process
from multiprocessing import Manager
class Test:
def __init__(self):
self.is_running = True
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, self._signal_handler)
signal.signal(signal.SIGINT, self._signal_handler)
signal.signal(signal.SIGTERM, self._signal_handler)
def _signal_handler(self, signum, frame):
"""
Terminate scenario ticking when receiving a signal interrupt
"""
self.is_running = False
print('关闭场景调度')
def listen_manage(self, running, kill_task_lst):
"""监控取消任务"""
if sys.platform != 'win32':
signal.signal(signal.SIGHUP, signal.SIG_IGN)
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while running.value:
kill_task_lst.append(1)
time.sleep(1)
print("child is running")
def run(self):
"""启动场景调度"""
kill_task_lst = Manager().list()
running = Manager().Value(bool, True)
print('启动监控进程')
p = Process(target=self.listen_manage, args=(running, kill_task_lst, ))
p.start()
while self.is_running:
time.sleep(0.5)
print("main is running")
running.set(False)
while p.is_alive():
time.sleep(0.01)
print("finish.....")
if __name__ == '__main__':
t = Test()
t.run()
执行结果:
启动监控进程
main is running
main is running
child is running
main is running
关闭场景调度
main is running
child is running
finish.....
最新文章
- 【iCore3 双核心板】【发布基于 iCore3的显示模块(包含7寸屏,4.3寸屏,vga模块等】
- 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
- Angular--$http服务
- Git远程和分支管理
- Apache Rewrite 拟静态配置
- 了解 JavaScript 应用程序中的内存泄漏
- NT内存
- json字符串转json对象的方法
- Javascript 命名空间模式
- 配置phpmyadmin使登录时可填写IP管理多台MySQL 连接多个数据库 自动登录
- Away3D 的实体收集器Bug
- 你以为你了解最常用的string.substring()的几个常见问题吗?
- Qt使用快捷键
- 深入理解Linux网络技术内幕——中断与网络驱动程序
- symbol(s) not found for architecture i386
- ubuntu 笔记
- Stack类常用api
- Temporal Action Detection with Structured Segment Networks (ssn)【转】
- composer命令中 --prefer-dist 和 --prefer-source 的区别
- mp4格式(转帖加修改) 转载