Builtin input does not always correctly handle errors from `PyOS_Readline`
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 77.2k
- Forks
- 35.9k
- PR merge metrics
- PR metrics pending
Description
Assertion failure sending SIGINT while calling input
import os, signal, threading
send = threading.Event()
def interrupter():
while True:
send.wait()
os.kill(os.getpid(), signal.SIGINT)
threading.Thread(target=interrupter).start()
send.set()
while True:
try:
input(">")
except KeyboardInterrupt:
pass
Note, this is a modified version of the example code in #112585.
Python (tested v3.12.10, v3.13.3, v3.14.0b1, and current HEAD), built with assertions enabled:
~/src/cpython/ $ ./python crash.py
>>>>>>>>>>>python: Objects/call.c:342: _PyObject_Call: Assertion `!_PyErr_Occurred(tstate)' failed.
Aborted (core dumped)
IIUC the issue is builtin_input_impl in Python/bltinmodule.c calls PyOS_Readline but assumes it cannot set an exception:
s = PyOS_Readline(stdin, stdout, promptstr);
if (s == NULL) {
PyErr_CheckSignals();
if (!PyErr_Occurred())
PyErr_SetNone(PyExc_KeyboardInterrupt);
If PyOS_Readline sets an exception (e.g. as in this case by running an interrupt signal handler itself), as opposed to being interrupted by a signal and returning NULL without setting the exception, and another signal with a handler is pending when PyErr_CheckSignals() is called, the handler will be called with the prior exception already set, and hence the assertion fails.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
No response
Linked PRs
- gh-134645
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in Python/bltinmodule.c at builtin_input_impl and reproduce the assertion with the provided signal and input example. Trace how PyOS_Readline and PyErr_CheckSignals handle an existing exception; done means the reproduction no longer aborts with the _PyObject_Call assertion and preserves the intended interrupt behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100