ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

can only join a child process

2021-11-30 12:33:25  阅读:212  来源: 互联网

标签:join signal process self worker only 进程 workers


上次 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 会继承当前进程的信号处理回调函数以及协程,其实就是拷贝了整个当前进程,准确点说是写时拷贝,如果只是读的话,那读的都和原来进程是同一个内存。

明白了这一点,问题就很清晰了。

标签:join,signal,process,self,worker,only,进程,workers
来源: https://www.cnblogs.com/flipped/p/15623647.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有