然后我们在Interactive Python prompt中测试了一下:
> import subprocess > subprocess.check_call("false") 0
而在其他机器运行相同的代码时, 却正确的抛出了错误:
> subprocess.check_call("false") Traceback (most recent call last): File "", line 1, in File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 542, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command 'false' returned non-zero exit status 1
看来是subprecess误以为子进程成功的退出了导致的原因.
深入分析
第一眼看上去, 这一问题应该是Python自身或操作系统引起的. 这到底是怎么发生的"htmlcode">
def wait(self): """Wait for child process to terminate. Returns returncode attribute.""" while self.returncode is None: try: pid, sts = _eintr_retry_call(os.waitpid, self.pid, 0) except OSError as e: if e.errno != errno.ECHILD: raise # This happens if SIGCLD is set to be ignored or waiting # for child processes has otherwise been disabled for our # process. This child is dead, we can't get the status. pid = self.pid sts = 0 # Check the pid and loop as waitpid has been known to return # 0 even without WNOHANG in odd situations. issue14396. if pid == self.pid: self._handle_exitstatus(sts) return self.returncode
可见, 如果os.waitpid的ECHILD检测失败, 那么错误就不会被抛出. 通常, 当一个进程结束后, 系统会继续记录其信息, 直到母进程调用wait()方法. 在此期间, 这一进程就叫"zombie". 如果子进程不存在, 那么我们就无法得知其是否成功还是失败了.
以上代码还能解决另外一个问题: Python默认认为子进程成功退出. 大多数情况下, 这一假设是没问题的. 但当一个进程明确表明忽略子进程的SIGCHLD时, waitpid()将永远是成功的.
回到原来的代码中
我们是不是在我们的程序中明确设置忽略SIGCHLD? 不太可能, 因为我们使用了大量的子进程, 但只有极少数情况下才出现同样的问题. 再使用git grep后, 我们发现只有在一段独立代码中, 我们忽略了SIGCHLD. 但这一代吗根本就不是程序的一部分, 只是引用了一下.
一星期后
一星期后, 这一错误又再一次发生. 并且通过简单的调试, 在debugger中重现了该错误.
经过一些测试, 我们确定了正是由于程序忽略了SIGCHLD才引起的这一bug. 但这是怎么发生的呢?
我们查看了那段独立代码, 其中有一段:
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
我们是不是无意间import了这段代码到程序中? 结果显示我们的猜测是正确的. 当import了这段代码后, 由于以上语句是在这一module的顶层, 而不是在一个function中, 导致了它的运行, 忽略了SIGCHLD, 从而导致了子进程错误没有被抛出!
总结
这一bug的发生, 给了我们两个教训. 第一是, 在debug检查时, 应该从新的代码到老的代码, 再到Python Library. 因为新代码发生错误的几率大于老代码, 而python library中发生错误的几率更小.
第二是, 不要将可能会引起副作用的代码写在module顶层, 而应当写到functuon中. 因为如果该module被import, 那么在顶层的代码就会运行, 导致各种不可知的事件发生.
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
更新日志
- 群星《2023好听新歌28》十倍音质 U盘音乐[WAV分轨][1G]
- faker拿了几个全球冠军 faker全球冠军数量介绍
- 英雄联盟faker拿了多少个冠军 Faker获得冠军数量介绍
- 英雄联盟全华班有夺冠过吗 英雄联盟全华班有没有夺过冠
- ChadCrouch-BartonCreekSoundwalk(2024)[24Bit-96kHz]FLAC
- BestAudiophileVoices4(2005)[FLAC]
- 常月《中国红》[DTS-WAV分轨]
- 国外《CS》选手抱怨上海major外设:桌子不能调节
- 美女推主COS合集图赏
- FS社母公司角川宣布:旗下共有26款游戏积极开发中!
- 黄莺莺.1984-炎夏的梦(2004环球复黑王)【宝丽金】【WAV+CUE】
- 黄雅莉.2009-雅莉不怕【福茂】【FLAC分轨】
- 张宇.1997-温古知新一个人的天荒地老【EMI百代】【WAV+CUE】
- 「灵与火的织卷」前瞻讨论开启 参与赢原石
- 【原神手游】原神基尼奇生日快乐