Skip to content

coverage uses open() which means it is impossible to run tests under conditions where opening files is not possible #2091

@glyph

Description

@glyph

Describe the bug
Twisted has some tests which intentionally exhaust the limit of open file descriptors in order to verify the real-world robustness of error handling behaviors in that scenario, of various APIs (particularly those which involve receiving EMFILE when calling .accept() on sockets, which is challenging to mock comprehensively).

Coverage then fails like this:

Traceback (most recent call last):
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/twisted/internet/tcp.py", line 1414, in doRead
    for accepted, (skt, addr) in enumerate(clients, 1):
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/twisted/internet/tcp.py", line 1210, in _accept
    with reservedFD:
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/twisted/internet/tcp.py", line 1016, in __enter__
    if self._fileDescriptor is None:
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/coverage/sysmon.py", line 433, in sysmon_branch_either
    multiline_map = get_multiline_map(code.co_filename)
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/coverage/sysmon.py", line 473, in get_multiline_map
    parser = PythonParser(filename=filename)
  File "/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/coverage/parser.py", line 61, in __init__
    raise NoSource(f"No source for code: '{self.filename}': {err}") from err
coverage.exceptions.NoSource: No source for code: '/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/twisted/internet/tcp.py': [Errno 24] Too many open files: '/home/runner/work/twisted/twisted/.tox/nodeps-withcov-posix/lib/python3.14/site-packages/twisted/internet/tcp.py'

Which you can see here: twisted/twisted#12535

To Reproduce

  1. Call open() (or similar) until you start getting OSError exceptions
  2. Leave all those files open
  3. Run coverage until it needs to open a Python source file for some reason.

Answer the questions below:

  1. What version of Python are you using? 3.14
  2. What version of coverage.py shows the problem? The output of coverage debug sys is helpful.
    -- sys -------------------------------------------------------
               coverage_version: 7.11.3
                coverage_module: /Users/glyph/.virtualenvs/Twisted/lib/python3.13/site-packages/coverage/__init__.py
                           core: -none-
                        CTracer: available from /Users/glyph/.virtualenvs/Twisted/lib/python3.13/site-packages/coverage/tracer.cpython-313-darwin.so
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: /Users/glyph/Projects/Twisted/.coveragerc
                   configs_read: /Users/glyph/Projects/Twisted/.coveragerc
                    config_file: /Users/glyph/Projects/Twisted/.coveragerc
                config_contents: b'[run]\nbranch = True\nparallel = True\nsource = twisted\nomit =\n    .tox/*/tmp/_trial_temp/*\n    */twisted/internet/gtk2reactor.py\n\n[paths]\nsource=\n   src/twisted\n   */src/twisted\n   */site-packages/twisted\n   benchmarks\n\n[report]\nprecision = 2\nignore_errors = True\nexclude_lines =\n    pragma: no cover\n    if TYPE_CHECKING\n    \\s*\\.\\.\\.$\n    raise NotImplementedError\n'
                      data_file: -none-
                         python: 3.13.8 (v3.13.8:a15ae614deb, Oct  7 2025, 08:28:01) [Clang 16.0.0 (clang-1600.0.26.6)]
                       platform: macOS-26.1-arm64-arm-64bit-Mach-O
                 implementation: CPython
                          build: v3.13.8:a15ae614deb
                                 Oct  7 2025 08:28:01
                    gil_enabled: True
                     executable: /Users/glyph/.virtualenvs/Twisted/bin/python3
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 98077
                            cwd: /Users/glyph/Projects/Twisted
                           path: /Users/glyph/.virtualenvs/Twisted/bin
                                 /Library/Frameworks/Python.framework/Versions/3.13/lib/python313.zip
                                 /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13
                                 /Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/lib-dynload
                                 /Users/glyph/.virtualenvs/Twisted/lib/python3.13/site-packages
                                 /Users/glyph/Projects/Twisted/src
                    environment: HOME = /Users/glyph
                                 PYTHONSTARTUP = /Users/glyph/Settings/Python/prompt.py
                                 VIRTUALENVWRAPPER_PYTHON = /Users/glyph/.local/pipx/venvs/virtualenvwrapper/bin/python
                   command_line: /Users/glyph/.virtualenvs/Twisted/bin/coverage debug sys
                           time: 2025-11-17 12:20:06
    
    
  3. What versions of what packages do you have installed? The output of pip freeze is helpful.
    alabaster==0.7.16
    anyio==4.11.0
    appdirs==1.4.4
    appnope==0.1.4
    astroid==4.0.2
    asttokens==3.0.1
    attrs==25.4.0
    Automat==25.4.16
    babel==2.17.0
    bcrypt==5.0.0
    blessed==1.24.0
    bpython==0.26
    CacheControl==0.14.4
    certifi==2025.11.12
    cffi==2.0.0
    charset-normalizer==3.4.4
    click==8.3.1
    comm==0.2.3
    ConfigArgParse==1.7.1
    constantly==23.10.4
    coverage==7.11.3
    cryptography==46.0.3
    curtsies==0.4.3
    cwcwidth==0.1.12
    cython-test-exception-raiser==1.0.2
    debugpy==1.8.17
    decorator==5.2.1
    dill==0.4.0
    docutils==0.18.1
    epc==0.0.5
    executing==2.2.1
    filelock==3.20.0
    greenlet==3.2.4
    h11==0.16.0
    h2==4.3.0
    hpack==4.1.0
    httpcore==1.0.9
    httpx==0.28.1
    hyperframe==6.1.0
    hyperlink==21.0.0
    hypothesis==6.148.1
    idna==3.11
    imagesize==1.4.1
    importmagic==0.1.7
    incremental==24.7.2
    ipykernel==7.1.0
    ipython==9.7.0
    ipython_pygments_lexers==1.1.1
    iso8601==2.1.0
    isort==7.0.0
    jedi==0.19.2
    Jinja2==3.1.6
    jupyter_client==8.6.3
    jupyter_core==5.9.1
    lunr==0.8.0
    MarkupSafe==3.0.3
    matplotlib-inline==0.2.1
    mccabe==0.7.0
    msgpack==1.1.2
    mypy==1.10.1
    mypy-zope==1.0.6
    mypy_extensions==1.1.0
    nest-asyncio==1.6.0
    packaging==25.0
    parso==0.8.5
    pexpect==4.9.0
    platformdirs==4.5.0
    priority==1.3.0
    prompt_toolkit==3.0.52
    psutil==7.1.3
    ptyprocess==0.7.0
    pudb==2025.1.3
    pure_eval==0.2.3
    pyasn1==0.6.1
    pyasn1_modules==0.4.2
    pycparser==2.23
    pydoctor==25.4.0
    pyflakes==2.5.0
    Pygments==2.19.2
    PyHamcrest==2.1.0
    pylint==4.0.3
    pyobjc-core==12.1
    pyobjc-framework-CFNetwork==12.1
    pyobjc-framework-Cocoa==12.1
    pyOpenSSL==25.3.0
    pyserial==3.5
    python-dateutil==2.9.0.post0
    python-subunit==1.4.5
    pyxdg==0.28
    pyzmq==27.1.0
    requests==2.32.5
    service-identity==24.2.0
    setuptools==80.9.0
    sexpdata==1.0.2
    six==1.17.0
    sniffio==1.3.1
    snowballstemmer==3.0.1
    sortedcontainers==2.4.0
    Sphinx==6.2.1
    sphinx-rtd-theme==1.3.0
    sphinxcontrib-applehelp==2.0.0
    sphinxcontrib-devhelp==2.0.0
    sphinxcontrib-htmlhelp==2.1.0
    sphinxcontrib-jquery==4.1
    sphinxcontrib-jsmath==1.0.1
    sphinxcontrib-qthelp==2.0.0
    sphinxcontrib-serializinghtml==2.0.0
    stack-data==0.6.3
    testtools==2.8.0
    tomlkit==0.13.3
    tornado==6.5.2
    towncrier==23.11.0
    traitlets==5.14.3
    -e git+https://github.com/twisted/twisted@cb828df6884ba0ceda00631533c57767537a9c56#egg=Twisted
    twistedchecker==0.7.4
    types-cffi==1.17.0.20250915
    types-pyOpenSSL==24.1.0.20240722
    types-setuptools==80.9.0.20250822
    typing_extensions==4.15.0
    urllib3==2.5.0
    urwid==2.6.16
    urwid_readline==0.15.1
    wcwidth==0.2.14
    wsproto==1.3.1
    zope.event==6.1
    zope.interface==8.1.1
    zope.schema==8.1
    
  4. What code shows the problem? Give us a specific commit of a specific repo that we can check out. If you've already worked around the problem, please provide a commit before that fix.
    https://github.com/twisted/twisted/blob/1af796ae654acc2f947c3420d9950d3f4a3113b8/src/twisted/internet/test/test_tcp.py#L966-L1038 but you probably don't actually want to read all of that
  5. What commands should we run to reproduce the problem? Be specific. Include everything, even git clone, pip install, and so on. Explain like we're five!
    tox -e withcov should do it, but only on some systems. I'm not sure why this only started happening recently and only in certain environments

Expected behavior

It's understandable that coverage normally expects to run under conditions where opening files is possible. However, under precise integration test conditions, both EMFILE exhaustion and system-under-test sensitivity to exact file descriptor numbers may cause this behavior to perturb the code being tested. My preference would be for a public API to allow for eager allocation of source code maps or any other external resource which may otherwise require external I/O at unpredictable points in execution.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfixed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions