起因

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

multiprocessing 让子进程忽略信号,手动关闭子进程的更多相关文章

  1. wait & waitpid 以及子进程传给父进程的信号分析

    wait() 和 waitpid() wait() 系统调用挂起调用进程的执行直到有一个孩子终止.调用 wait(&status) 等价于: waitpid(-1, &status, ...

  2. Linux 父进程发送信号杀死子进程

    #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <signal. ...

  3. 第9章 Linux进程和信号超详细分析

    9.1 进程简单说明 进程是一个非常复杂的概念,涉及的内容也非常非常多.在这一小节所列出内容,已经是我极度简化后的内容了,应该尽可能都理解下来,我觉得这些理论比如何使用命令来查看状态更重要,而且不明白 ...

  4. node.js中process进程的概念和child_process子进程模块的使用

    进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...

  5. python的multiprocessing模块进程创建、资源回收-Process,Pool

    python的multiprocessing有两种创建进程的方式,每种创建方式和进程资源的回收都不太相同,下面分别针对Process,Pool及系统自带的fork三种进程分析. 1.方式一:fork( ...

  6. 初步理解Python进程的信号通讯

    Reference: http://www.jb51.net/article/63787.htm 信号的概念 信号(signal)--     进程之间通讯的方式,是一种软件中断.一个进程一旦接收到信 ...

  7. python之multiprocessing创建进程

    python的multiprocessing模块是用来创建多进程的,下面对multiprocessing总结一下使用记录. multiprocessing创建多进程在windows和linux系统下的 ...

  8. Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存

    Linux进程间通信--进程,信号,管道,消息队列,信号量,共享内存 参考:<linux编程从入门到精通>,<Linux C程序设计大全>,<unix环境高级编程> ...

  9. Python多进程库multiprocessing创建进程以及进程池Pool类的使用

    问题起因最近要将一个文本分割成好几个topic,每个topic设计一个regressor,各regressor是相互独立的,最后汇总所有topic的regressor得到总得预测结果.没错!类似bag ...

随机推荐

  1. 根据数据中的key获取value值

    一.测试数据准备 List<Map<String, String>> result = new ArrayList();Map<String, String> ma ...

  2. RPA-UiPath视频教程2

    UiPath参数的介绍和使用 https://www.bilibili.com/video/av83343849 UiPath第一个案例HelloWorld https://www.bilibili. ...

  3. Unity-A-Star寻路算法

    最短路径 将地图存成二维数组,通过行列查找: 每一步都查找周围四个方向,或者八方向的所有点,放入开表: 是否边缘 是否障碍 是否已经在确定的路线中 计算每个方向上路径消耗,一般斜着走消耗小,收益大: ...

  4. 全国降雨侵蚀力因子R值

      数据下载链接:百度云下载链接​ 降雨侵蚀力因子其实是反应降雨对土壤侵蚀的潜在能力,就是降雨的冲刷对土壤的侵蚀效应. 在过去几天查阅文献资料的过程中,本人亲眼看见过的关于因子R的计算方法就超过30种 ...

  5. Whats On Tap | Tapdata Cloud 如何助力大型家居连锁商城推进数字化经营?

    Tapdata Cloud 的操作有多便捷,上手试一下就能充分了解了.--Tapdata Cloud 用户 | 报表实施 @某大型家居服务平台 一边是监管政策趋严,推动房地产回归本源,存量竞争时代开启 ...

  6. Hashtable集合 --练习题_计算一个字符串中每个字符出现次数

    Hashtable集合 java.util.Hashtable<K,V>集合 implements Map<K,V>接口  Hashtable:底层也是一个哈希表,是一个线程安 ...

  7. jupyter 反向代理配置

    抓了下包,看了一下WS连不上,参考这个,问题解决 location / { proxy_pass http://127.0.0.1:8813/; # JUPYTER_PORT 为 Jupyter 运行 ...

  8. python requests 使用代理池访问https站点返回乱码

    问题表现: 检查一下正常的请求头里面accept-encoding字段是否包含br,如果包含,果断pip install urllib3[brotli],详见ssl-warnings 记录另外一个问题 ...

  9. Vue中关于this指向的问题

    由Vue管理的函数 例如: computed 计算属性 watch 监视属性 filters (Vue3中已弃用且不再支持) 过滤器 .... 上述属性里配置的函数不要采用箭头函数写法,因为箭头函数没 ...

  10. Educational Codeforces Round 132 (C,D) 题解 cf#1709

    昨晚打了这把EDU,赛后看了dalao们的C题代码豁然开朗恍然大悟 实在是太巧妙了 这场来说,D题的通过率比C题高太多了(估计很多人都在C题卡了然后没做D 先放题目链接 题目链接 C - Recove ...