pytest-dev / pytest-dev/pytest

`OSError: [Errno 9] Bad file descriptor` in terminalwritter

Open
#10,434 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: bug
Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

I have a nightly test run via Jenkins which takes around 8 hours. Pytest runs with live logging so there is thousands of lines output to stdout during the run. Around once per month I get a crash in pytest which kills the run. There is nothing obviously different to explain why pytest crashes on particular runs.

It looks from the traceback like it cannot write to the terminal.

I'm happy to do some work on fixing this, but I will need some guidance from someone who knows the internals of pytest.

OS (where pytest is running)

OS Name: Microsoft Windows 10 Pro
OS Version: 10.0.19044 N/A Build 19044

pytest version

7.1.3

Traceback
INERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\main.py", line 268, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\main.py", line 322, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
INTERNALERROR>     return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\main.py", line 347, in pytest_runtestloop
INTERNALERROR>     item.config.hook.pytest_runtest_protocol(item=item, nextitem=nextitem)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
INTERNALERROR>     return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\runner.py", line 111, in pytest_runtest_protocol
INTERNALERROR>     runtestprotocol(item, nextitem=nextitem)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\runner.py", line 130, in runtestprotocol
INTERNALERROR>     reports.append(call_and_report(item, "call", log))
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\runner.py", line 223, in call_and_report
INTERNALERROR>     hook.pytest_runtest_logreport(report=report)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_hooks.py", line 265, in __call__
INTERNALERROR>     return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_manager.py", line 80, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 60, in _multicall
INTERNALERROR>     return outcome.get_result()
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_result.py", line 60, in get_result
INTERNALERROR>     raise ex[1].with_traceback(ex[2])
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\pluggy\_callers.py", line 39, in _multicall
INTERNALERROR>     res = hook_impl.function(*args)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\terminal.py", line 561, in pytest_runtest_logreport
INTERNALERROR>     self._write_progress_information_filling_space()
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\terminal.py", line 624, in _write_progress_information_filling_space
INTERNALERROR>     self.write(msg.rjust(fill), flush=True, **{color: True})
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\terminal.py", line 414, in write
INTERNALERROR>     self._tw.write(content, flush=flush, **markup)
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\_io\terminalwriter.py", line 167, in write
INTERNALERROR>     self.flush()
INTERNALERROR>   File "C:\jenkins\workspace\my-project\.venv\lib\site-packages\_pytest\_io\terminalwriter.py", line 174, in flush
INTERNALERROR>     self._file.flush()
INTERNALERROR> OSError: [Errno 9] Bad file descriptor
pip list
Package               Version
--------------------- ---------
allure-pytest         2.11.1
allure-python-commons 2.11.1
astroid               2.12.12
atomicwrites          1.4.1
attrs                 22.1.0
bcrypt                3.2.2
black                 22.10.0
certifi               2022.6.15
cffi                  1.15.1
charset-normalizer    2.1.0
click                 8.1.3
colorama              0.4.5
cryptography          37.0.4
cycler                0.11.0
dill                  0.3.5.1
fonttools             4.34.4
future                0.18.2
idna                  3.3
iniconfig             1.1.1
invoke                1.7.3
isort                 5.10.1
kiwisolver            1.4.4
lazy-object-proxy     1.7.1
matplotlib            3.5.2
mccabe                0.7.0
mypy                  0.982
mypy-extensions       0.4.3
netmiko               4.1.1
ntc-templates         3.0.0
numpy                 1.21.6
packaging             21.3
paramiko              2.11.0
pathspec              0.9.0
Pillow                9.2.0
pip                   21.1.1
platformdirs          2.5.2
pluggy                1.0.0
py                    1.11.0
pycparser             2.21
pydocstyle            6.1.1
pylint                2.15.5
pylint-pytest         1.1.2
PyNaCl                1.5.0
pyparsing             3.0.9
pyserial              3.5
pytest                7.1.3
python-dateutil       2.8.2
python-nmap           0.7.1
PyYAML                6.0
requests              2.28.1
scipy                 1.8.1
scp                   0.14.4
setuptools            65.5.0
six                   1.16.0
snowballstemmer       2.2.0
sounddevice           0.4.4
tenacity              8.0.1
textfsm               1.1.3
toml                  0.10.2
tomli                 2.0.1
tomlkit               0.11.1
types-python-nmap     0.7.1
types-requests        2.28.11.2
types-urllib3         1.26.17
typing-extensions     4.3.0
urllib3               1.26.11
wheel                 0.38.0
wrapt                 1.14.1
  • a detailed description of the bug or problem you are having
  • output of pip list from the virtual environment you are using
  • pytest and operating system versions
  • minimal example if possible

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading _pytest/_io/terminalwriter.py around flush() and the _pytest/terminal.py call sites shown in the traceback. Reproduce the Windows 10 Jenkins scenario with a long-running pytest session and live logging, then determine the conditions around the bad file descriptor. Done means the intermittent crash is reproduced and a verified fix or clear limitation is covered by relevant tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.