起因

同事想要写一个代码,主进程中监听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.....

最新文章

  1. 【iCore3 双核心板】【发布基于 iCore3的显示模块(包含7寸屏,4.3寸屏,vga模块等】
  2. 教你分分钟学会用python爬虫框架Scrapy爬取心目中的女神
  3. Angular--$http服务
  4. Git远程和分支管理
  5. Apache Rewrite 拟静态配置
  6. 了解 JavaScript 应用程序中的内存泄漏
  7. NT内存
  8. json字符串转json对象的方法
  9. Javascript 命名空间模式
  10. 配置phpmyadmin使登录时可填写IP管理多台MySQL 连接多个数据库 自动登录
  11. Away3D 的实体收集器Bug
  12. 你以为你了解最常用的string.substring()的几个常见问题吗?
  13. Qt使用快捷键
  14. 深入理解Linux网络技术内幕——中断与网络驱动程序
  15. symbol(s) not found for architecture i386
  16. ubuntu 笔记
  17. Stack类常用api
  18. Temporal Action Detection with Structured Segment Networks (ssn)【转】
  19. composer命令中 --prefer-dist 和 --prefer-source 的区别
  20. mp4格式(转帖加修改) 转载

热门文章

  1. 粗谈对ajax的理解
  2. React与Koa一起打造一个功能丰富的全栈个人博客(业务篇)
  3. SAP Display picture
  4. SAP Html viewer
  5. SAP IDOC
  6. UiPath Orchestrator安装步骤
  7. NC24724 [USACO 2010 Feb S]Chocolate Eating
  8. rust实现http时如何读取一个完整的request
  9. 基于gRPC编写golang简单C2远控
  10. PLC转OPC UA的协议转换网关需要多少钱呢?