国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

深入分析在Python模塊頂層運(yùn)行的代碼引起的一個Bug

2020-02-23 05:30:45
字體:
供稿:網(wǎng)友

然后我們在Interactive Python prompt中測試了一下:

>>> import subprocess  >>> subprocess.check_call("false")  0

而在其他機(jī)器運(yùn)行相同的代碼時, 卻正確的拋出了錯誤:

>>> 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誤以為子進(jìn)程成功的退出了導(dǎo)致的原因.

深入分析

第一眼看上去, 這一問題應(yīng)該是Python自身或操作系統(tǒng)引起的. 這到底是怎么發(fā)生的? 于是我的同事查看了subprocess的wait()方法:

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檢測失敗, 那么錯誤就不會被拋出. 通常, 當(dāng)一個進(jìn)程結(jié)束后, 系統(tǒng)會繼續(xù)記錄其信息, 直到母進(jìn)程調(diào)用wait()方法. 在此期間, 這一進(jìn)程就叫"zombie". 如果子進(jìn)程不存在, 那么我們就無法得知其是否成功還是失敗了.

以上代碼還能解決另外一個問題: Python默認(rèn)認(rèn)為子進(jìn)程成功退出. 大多數(shù)情況下, 這一假設(shè)是沒問題的. 但當(dāng)一個進(jìn)程明確表明忽略子進(jìn)程的SIGCHLD時, waitpid()將永遠(yuǎn)是成功的.

回到原來的代碼中

我們是不是在我們的程序中明確設(shè)置忽略SIGCHLD? 不太可能, 因為我們使用了大量的子進(jìn)程, 但只有極少數(shù)情況下才出現(xiàn)同樣的問題. 再使用git grep后, 我們發(fā)現(xiàn)只有在一段獨(dú)立代碼中, 我們忽略了SIGCHLD. 但這一代嗎根本就不是程序的一部分, 只是引用了一下.

一星期后

一星期后, 這一錯誤又再一次發(fā)生. 并且通過簡單的調(diào)試, 在debugger中重現(xiàn)了該錯誤.

經(jīng)過一些測試, 我們確定了正是由于程序忽略了SIGCHLD才引起的這一bug. 但這是怎么發(fā)生的呢?

我們查看了那段獨(dú)立代碼, 其中有一段:

signal.signal(signal.SIGCHLD, signal.SIG_IGN)
我們是不是無意間import了這段代碼到程序中? 結(jié)果顯示我們的猜測是正確的. 當(dāng)import了這段代碼后, 由于以上語句是在這一module的頂層, 而不是在一個function中, 導(dǎo)致了它的運(yùn)行, 忽略了SIGCHLD, 從而導(dǎo)致了子進(jìn)程錯誤沒有被拋出!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 交口县| 天水市| 昌宁县| 资溪县| 南充市| 辽源市| 鄯善县| 临汾市| 米易县| 吉木萨尔县| 和田县| 北流市| 郴州市| 永平县| 庆阳市| 靖边县| 汉川市| 逊克县| 秦安县| 河北区| 泸西县| 庆元县| 大同市| 屯昌县| 英超| 巢湖市| 田阳县| 大荔县| 兰州市| 宣化县| 石首市| 昌乐县| 衡东县| 封丘县| 安徽省| 三门峡市| 怀仁县| 六安市| 滁州市| 邹城市| 资兴市|