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

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


    ┆凉┆暖┆降┆等┆幸┆我┆我┆里┆将┆ ┆可┆有┆谦┆戮┆那┆ ┆大┆始┆ ┆然┆
    ┆薄┆一┆临┆你┆的┆还┆没┆ ┆来┆ ┆是┆来┆逊┆没┆些┆ ┆雁┆终┆ ┆而┆
    ┆ ┆暖┆ ┆如┆地┆站┆有┆ ┆也┆ ┆我┆ ┆的┆有┆精┆ ┆也┆没┆ ┆你┆
    ┆ ┆这┆ ┆试┆方┆在┆逃┆ ┆会┆ ┆在┆ ┆清┆来┆准┆ ┆没┆有┆ ┆没┆
    ┆ ┆生┆ ┆探┆ ┆最┆避┆ ┆在┆ ┆这┆ ┆晨┆ ┆的┆ ┆有┆来┆ ┆有┆
    ┆ ┆之┆ ┆般┆ ┆不┆ ┆ ┆这┆ ┆里┆ ┆没┆ ┆杀┆ ┆来┆ ┆ ┆来┆
  • 相关阅读:
    网站性能优化分类总结
    关于高度塌陷问题解决方法
    语义化HTML
    CSS命名规范
    linux开机过程
    Linux--sed命令
    博客声明
    linux-- grep命令
    pyinstaller使用-python项目转换成exe可执行文件
    python导出开发环境
  • 原文地址:https://www.cnblogs.com/flipped/p/15623647.html
Copyright © 2020-2023  润新知