can only join a child process
2023-03-20 15:31:00 时间
上次 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 会继承当前进程的信号处理回调函数以及协程,其实就是拷贝了整个当前进程,准确点说是写时拷贝,如果只是读的话,那读的都和原来进程是同一个内存。
明白了这一点,问题就很清晰了。
相关文章
- HTML5(四)——Web Workers
- 一个运维人员的编程思维2
- HTML5(五)——Canvas API
- 一个运维人员的编程思维3
- 一个运维人员的编程思维4
- HTML5(六)——Canvas 高级操作
- 一个运维人员的编程思维5
- 一个运维人员的编程思维6
- Redis Cluster集群扩容主从节点详细教程
- 不会吧,你还不会用RequestId看日志 ?
- 基于NOSTR协议的“公有制”版本的Twitter,去中心化社交软件Damus用后感,一个极端走向另一个极端
- 前端架构师神技,三招统一代码风格(一文讲透)
- 404星链计划 | As-Exploits:中国蚁剑后渗透框架
- 2022,烟火如常,布衣剩饭,啥也没干,年终总结,蹈海难酬
- 404星链计划 | Platypus:支持多会话的交互式反向 Shell 管理器
- 404星链计划 | ysomap : Java反序列化利用框架
- 最新系统MacOs13 Ventura(M1/M2芯片) + Parallels Desktop 18(PD18史上最强虚拟机)永久使用攻略
- 用 SwiftUI 实现 3D Scroll 效果
- 深入了解Webpack 5
- 巧如范金,精比琢玉,一分钟高效打造精美详实的Go语言技术简历(Golang1.18)