can only join a child process
上次 gevent.hub.BlockingSwitchOutError: Impossible to call blocking function in the event loop callback 这篇文章记录的优雅退出的问题,前后还有些东西想记录一下。
一开始遇到的问题是本地运行某个服务(声明一下不是我写的),ctrl+c 结束时报错:
File "/usr/local/lib/python3.6/multiprocessing/process.py", line 122, in join
assert self._parent_pid == os.getpid(), 'can only join a child process'
经过调查(看代码查资料),发现原来是因为在启动多进程之前注册了信号处理的回调函数,并且在回调函数最后执行了对多进程的 join。有点像这样:
def run(self):
...
def start(self):
# 注册 SIGINT 信号的回调函数
signal.signal(signal.SIGINT, self.graceful_exit)
# 启动一个心跳协程
self.heartbeat_task = gevent.spawn(self.heartbeat)
# 创建子进程
self.workers = [multiprocessing.Process(
target=self.run) for _ in range(4)]
for worker in self.workers:
worker.start()
def graceful_exit(self, sig, frame):
...
# join 是等待进程结束
for worker in self.workers:
worker.join()
另外一点是,还在创建子进程前创建了一个 gevent 协程。而被用来的开发者忽略掉的重要问题就是:
创建子进程,也就是调用了操作系统的 fork,而 fork 会继承当前进程的信号处理回调函数以及协程,其实就是拷贝了整个当前进程,准确点说是写时拷贝,如果只是读的话,那读的都和原来进程是同一个内存。
明白了这一点,问题就很清晰了。
┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2016-11-30 【USACO 3.2】Sweet Butter(最短路)
2016-11-30 【USACO 3.2】Magic Squares
2015-11-30 【codevs1014/1068】背包型动态规划