当从子进程调用Python程序时,它将永远挂起

当从子进程调用Python程序时,它将永远挂起,python,subprocess,Python,Subprocess,pip测试套件使用子流程调用来运行集成测试。最近发布了一个PR,删除了一些旧的兼容性代码。具体地说,它将b()函数替换为显式使用b”“文本。然而,这似乎打破了某些特定子进程调用将永远挂起的地方。更糟糕的是,它只会永远挂在Python3.3(可能只有Python3.3.5)上,在Travis之外很难复制 相关请求: 其他Pull请求也会出现类似的问题,但是它们在不同版本的Python和不同的测试用例中失败。这些请求是: (还是Python 3.3) 另一位用户今天在IRC上向我报告

pip测试套件使用子流程调用来运行集成测试。最近发布了一个PR,删除了一些旧的兼容性代码。具体地说,它将
b()
函数替换为显式使用
b”“
文本。然而,这似乎打破了某些特定子进程调用将永远挂起的地方。更糟糕的是,它只会永远挂在Python3.3(可能只有Python3.3.5)上,在Travis之外很难复制

相关请求:

其他Pull请求也会出现类似的问题,但是它们在不同版本的Python和不同的测试用例中失败。这些请求是:

  • (还是Python 3.3)
另一位用户今天在IRC上向我报告了一个类似的问题,他们说他们可以在Ubuntu14.04上用Python3.3从deadsnakes(但不是在OSX上)本地复制它,而不仅仅是在Travis上,就像我到目前为止所能做的那样。他们向我发送了复制步骤,其中包括:

$git克隆git@github.com:xavfernandez/pip.git
$cd点子
$git签出调试\u卡住
$pip install pytest==2.5.2 scripttest==1.3 virtualenv==1.11.6 mock==1.0.1假装==1.0.8 setuptools==4.0
$#下面的内容应该可以通过
$py.test-k test\u env\u vars\u override\u config\u file-v-s
$#现在编辑pip/req/req_set.py并删除方法remove_me_to_block或将其内容更改为print('KO')或pass
$#下面应该永远挂着
$py.test-k test\u env\u vars\u override\u config\u file-v-s
在上面的示例中,
remove_me_to_block
方法没有在任何地方调用,仅仅存在它就足以使测试不成块,而不存在它(或更改它的内容)就足以使测试块永远存在

大多数调试都与此PR()中的更改有关。一次推送一个提交后,测试通过,直到应用了这个特定的提交-。具体地说,更改为使用
b'\r\n'
(entry+endline).encode(“utf-8”)
将触发它,但是这两种情况都不在它无法执行的命令
pip install-vvv INITools
的执行路径中

在试图追踪问题的过程中,我注意到,如果我用
(lambda:“something”)().encode(“utf8”)
替换至少一个对
“something.encode”(“utf8”)
的调用,它就会工作

在尝试调试时的另一个问题是,我尝试过的各种方法(添加print语句、no op
atexit
函数、对异步子流程使用trollious)只会将问题从特定Python版本上的特定测试用例转移到不同Python版本上的不同测试用例

我知道,如果直接从
subprocess.Popen().stdout/stderr/stdin
读取/写入,那么
子进程
模块可能会死锁。但是,此代码使用的是
communicate()
方法,该方法应该可以解决这些问题。在
wait()
调用中,
communicate()
会使进程永远挂起,等待pip进程退出

其他资料:

  • 这是非常海森尼,我已经设法使它离开或转移的基础上,各种事情,不应该有任何影响
  • 我一直跟踪pip本身内部的执行情况,直到调用
    sys.exit()
    为止
  • sys.exit()
    替换为
    os.\u exit()
    修复了所有悬而未决的问题,但是我不希望这样做,因为我们将跳过Python解释器所做的清理
  • 没有其他正在运行的线程(通过
    线程。枚举
    验证)
  • 我做了一些更改组合,这些更改使它挂起,即使没有将
    subprocess.PIPE
    用于stdout/stderr/stdin,但是如果不使用这些更改组合,其他组合也不会挂起(或者它将转移到另一个测试用例/python版本)
  • 它似乎与时间无关,任何特定的提交都会在影响测试用例/python上失败100%,或者失败0%
  • 通常情况下,被更改的代码甚至没有被pip子流程中的特定代码路径执行,然而仅仅是更改的存在似乎就破坏了它
  • 我曾尝试使用
    pythontwritebytecode=1禁用字节码生成,这在一个组合中有效果,但在其他组合中没有效果
  • 子流程调用的命令不会在每次调用中挂起(通过测试套件发出类似的命令),但是对于特定的提交,它总是挂起在完全相同的位置
  • 到目前为止,除了在测试套件中通过
    subaccess
    调用之外,我完全无法重现这种情况,但是我不知道它是否与此相关
我完全不知道是什么导致了这一切

更新#1


使用
faulthandler.dump\u traceback\u later()
我得到了以下结果:

Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/requests/packages/urllib3/response.py", line 287 in closed
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/requests/packages/urllib3/response.py", line 287 in closed
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
Timeout (0:00:05)!
Current thread 0x00007f417bd92740:
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/requests/packages/urllib3/response.py", line 285 in closed
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
  [ Duplicate Lines Snipped ]
  File "/tmp/pytest-10/test_env_vars_override_config_file0/pip_src/pip/_vendor/cachecontrol/filewrapper.py", line 24 in __getattr__
这向我表明,问题可能与垃圾收集和urllib3有关?
pip.\u vendor.cachecontrol.Filewrapper
中的
Filewrapper
用作urllib3响应对象(其子类为
io.IOBase
)的包装器,因此我们可以使用
read()
方法将每个读取调用的结果存储在缓冲区中并返回它,然后,一旦文件被完全使用,使用该缓冲区的内容运行回调,以便我们可以将该项存储在缓存中。这会以某种方式与GC交互吗

更新#2

如果我添加一个
def\uu del\uuu(self):passgc: uncollectable <CallbackFileWrapper 0x7f66385c1cd0>
gc: uncollectable <dict 0x7f663821d5a8>
gc: uncollectable <functools.partial 0x7f663831de10>
gc: uncollectable <_io.BytesIO 0x7f663804dd50>
gc: uncollectable <method 0x7f6638219170>
gc: uncollectable <tuple 0x7f663852bd40>
gc: uncollectable <HTTPResponse 0x7f663831c7d0>
gc: uncollectable <PreparedRequest 0x7f66385c1a90>
gc: uncollectable <dict 0x7f663852cb48>
gc: uncollectable <dict 0x7f6637fdcab8>
gc: uncollectable <HTTPHeaderDict 0x7f663831cb90>
gc: uncollectable <CaseInsensitiveDict 0x7f66385c1ad0>
gc: uncollectable <dict 0x7f6638218ab8>
gc: uncollectable <RequestsCookieJar 0x7f663805d7d0>
gc: uncollectable <dict 0x7f66382140e0>
gc: uncollectable <dict 0x7f6638218680>
gc: uncollectable <list 0x7f6638218e18>
gc: uncollectable <dict 0x7f6637f14878>
gc: uncollectable <dict 0x7f663852c5a8>
gc: uncollectable <dict 0x7f663852cb00>
gc: uncollectable <method 0x7f6638219d88>
gc: uncollectable <DefaultCookiePolicy 0x7f663805d590>
gc: uncollectable <list 0x7f6637f14518>
gc: uncollectable <list 0x7f6637f285a8>
gc: uncollectable <list 0x7f6637f144d0>
gc: uncollectable <list 0x7f6637f14ab8>
gc: uncollectable <list 0x7f6637f28098>
gc: uncollectable <list 0x7f6637f14c20>
gc: uncollectable <list 0x7f6637f145a8>
gc: uncollectable <list 0x7f6637f14440>
gc: uncollectable <list 0x7f663852c560>
gc: uncollectable <list 0x7f6637f26170>
gc: uncollectable <list 0x7f663821e4d0>
gc: uncollectable <list 0x7f6637f2d050>
gc: uncollectable <list 0x7f6637f14fc8>
gc: uncollectable <list 0x7f6637f142d8>
gc: uncollectable <list 0x7f663821d050>
gc: uncollectable <list 0x7f6637f14128>
gc: uncollectable <tuple 0x7f6637fa8d40>
gc: uncollectable <tuple 0x7f66382189e0>
gc: uncollectable <tuple 0x7f66382183f8>
gc: uncollectable <tuple 0x7f663866cc68>
gc: uncollectable <tuple 0x7f6637f1e710>
gc: uncollectable <tuple 0x7f6637fc77a0>
gc: uncollectable <tuple 0x7f6637f289e0>
gc: uncollectable <tuple 0x7f6637f19f80>
gc: uncollectable <tuple 0x7f6638534d40>
gc: uncollectable <tuple 0x7f6637f259e0>
gc: uncollectable <tuple 0x7f6637f1c7a0>
gc: uncollectable <tuple 0x7f6637fc8c20>
gc: uncollectable <tuple 0x7f6638603878>
gc: uncollectable <tuple 0x7f6637f23440>
gc: uncollectable <tuple 0x7f663852c248>
gc: uncollectable <tuple 0x7f6637f2a0e0>
gc: uncollectable <tuple 0x7f66386a6ea8>
gc: uncollectable <tuple 0x7f663852f9e0>
gc: uncollectable <tuple 0x7f6637f28560>
gc: uncollectable <CallbackFileWrapper 0x7f66385c1350>
gc: uncollectable <dict 0x7f6638c33320>
gc: uncollectable <HTTPResponse 0x7f66385c1590>
gc: uncollectable <functools.partial 0x7f6637f03ec0>
gc: uncollectable <_io.BytesIO 0x7f663804d600>
gc: uncollectable <dict 0x7f6637f1f680>
gc: uncollectable <method 0x7f663902d3b0>
gc: uncollectable <tuple 0x7f663852be18>
gc: uncollectable <HTTPMessage 0x7f66385c1c10>
gc: uncollectable <HTTPResponse 0x7f66385c1450>
gc: uncollectable <PreparedRequest 0x7f66385cac50>
gc: uncollectable <dict 0x7f6637f2f248>
gc: uncollectable <dict 0x7f6637f28b90>
gc: uncollectable <dict 0x7f6637f1e638>
gc: uncollectable <list 0x7f6637f26cb0>
gc: uncollectable <list 0x7f6637f2f638>
gc: uncollectable <HTTPHeaderDict 0x7f66385c1f90>
gc: uncollectable <CaseInsensitiveDict 0x7f66385b2890>
gc: uncollectable <dict 0x7f6638bd9200>
gc: uncollectable <RequestsCookieJar 0x7f663805da50>
gc: uncollectable <dict 0x7f6637f28a28>
gc: uncollectable <dict 0x7f663853aa28>
gc: uncollectable <list 0x7f663853a6c8>
gc: uncollectable <dict 0x7f6638ede5f0>
gc: uncollectable <dict 0x7f6637f285f0>
gc: uncollectable <dict 0x7f663853a4d0>
gc: uncollectable <method 0x7f663911f710>
gc: uncollectable <DefaultCookiePolicy 0x7f663805d210>
gc: uncollectable <list 0x7f6637f28ab8>
gc: uncollectable <list 0x7f6638215050>
gc: uncollectable <list 0x7f663853a200>
gc: uncollectable <list 0x7f6638215a28>
gc: uncollectable <list 0x7f663853a950>
gc: uncollectable <list 0x7f663853a998>
gc: uncollectable <list 0x7f6637f21638>
gc: uncollectable <list 0x7f6637f0cd40>
gc: uncollectable <list 0x7f663853ac68>
gc: uncollectable <list 0x7f6637f22c68>
gc: uncollectable <list 0x7f663853a170>
gc: uncollectable <list 0x7f6637fa6a28>
gc: uncollectable <list 0x7f66382153b0>
gc: uncollectable <list 0x7f66386a5e60>
gc: uncollectable <list 0x7f663852f2d8>
gc: uncollectable <list 0x7f66386a3320>
    [<pip._vendor.cachecontrol.filewrapper.CallbackFileWrapper object at 0x7f66385c1cd0>, <pip._vendor.cachecontrol.filewrapper.CallbackFileWrapper object at 0x7f66385c1350>]