Sitelet https://github.com/python/cpython/issues/93249
Skip to content

Objects/codeobject.c:814: retreat: Assertion `bounds->ar_start > 0' failed #93249

Description

@The-Compiler

Crash report

Doing a pip install PyQt6 and then running the following script:

from PyQt6.QtCore import QUrl, QTimer, QCoreApplication

app = QCoreApplication([])
timer = QTimer()
timer.setInterval(10)
timer.timeout.connect(lambda: None)
timer.start()

print("Running")

app.exec()

and then pressing Ctrl-C (or running signal 2 in gdb) would normally produce:

Running
^CTraceback (most recent call last):
  File "/home/florian/tmp/repro.py", line 6, in <lambda>
    timer.timeout.connect(lambda: None)
KeyboardInterrupt

(in my case, it seems to crash with a SIGIOT after that, but let's ignore that for now...).

However, with Python 3.11.0b1 configured with --with-pydebug, this happens instead:

Running
^Cpython: Objects/codeobject.c:814: retreat: Assertion `bounds->ar_start > 0' failed.

referring to this line:

assert(bounds->ar_start > 0);

I was able to bisect this to 944fffe ("GH-88116: Use a compact format to represent end line and column offsets. (GH-91666)", @markshannon).

Error messages

Backtrace:

Details
#0  0x00007ffff7d1636c in ?? () from /usr/lib/libc.so.6
#1  0x00007ffff7cc6838 in raise () from /usr/lib/libc.so.6
#2  0x00007ffff7cb0535 in abort () from /usr/lib/libc.so.6
#3  0x00007ffff7cb045c in ?? () from /usr/lib/libc.so.6
#4  0x00007ffff7cbf366 in __assert_fail () from /usr/lib/libc.so.6
#5  0x00005555556d6b61 in retreat (bounds=bounds@entry=0x7fffffffbab0) at Objects/codeobject.c:799
#6  0x00005555556d9992 in PyCode_Addr2Location (co=<optimized out>, addrq=0, start_line=start_line@entry=0x7fffffffbb40, start_column=start_column@entry=0x7fffffffbb48, end_line=end_line@entry=0x7fffffffbb44, end_column=end_column@entry=0x7fffffffbb4c) at Objects/codeobject.c:902
#7  0x000055555581f36e in tb_displayline (tb=tb@entry=0x7ffff44aa7b0, f=f@entry=<_io.StringIO at remote 0x7ffff762b9d0>, filename='/home/florian/tmp/repro.py', lineno=6, frame=Frame 0x7ffff4498600, for file /home/florian/tmp/repro.py, line 6, in <lambda> (), name=<optimized out>, margin_indent=0, margin=0x5555558cc7df "") at Python/traceback.c:799
#8  0x000055555581f6e9 in tb_printinternal (tb=tb@entry=0x7ffff44aa7b0, f=f@entry=<_io.StringIO at remote 0x7ffff762b9d0>, limit=limit@entry=1000, indent=indent@entry=0, margin=margin@entry=0x5555558cc7df "") at Python/traceback.c:944
#9  0x000055555581f7f9 in _PyTraceBack_Print_Indented (v=v@entry=<traceback at remote 0x7ffff44aa7b0>, indent=0, margin=0x5555558cc7df "", header_margin=header_margin@entry=0x5555558cc7df "", header=0x555555930270 "Traceback (most recent call last):\n", f=f@entry=<_io.StringIO at remote 0x7ffff762b9d0>) at Python/traceback.c:1002
#10 0x000055555580b624 in print_exception_traceback (ctx=ctx@entry=0x7fffffffbd20, value=KeyboardInterrupt()) at Python/pythonrun.c:941
#11 0x000055555580c499 in print_exception (ctx=ctx@entry=0x7fffffffbd20, value=value@entry=KeyboardInterrupt()) at Python/pythonrun.c:1223
#12 0x000055555580c9d7 in print_exception_recursive (ctx=ctx@entry=0x7fffffffbd20, value=value@entry=KeyboardInterrupt()) at Python/pythonrun.c:1508
#13 0x000055555580cee9 in _PyErr_Display (file=file@entry=<_io.StringIO at remote 0x7ffff762b9d0>, exception=exception@entry=<type at remote 0x555555a18160>, value=value@entry=KeyboardInterrupt(), tb=tb@entry=<traceback at remote 0x7ffff44aa7b0>) at Python/pythonrun.c:1551
#14 0x000055555580d054 in PyErr_Display (exception=<type at remote 0x555555a18160>, value=KeyboardInterrupt(), tb=<traceback at remote 0x7ffff44aa7b0>) at Python/pythonrun.c:1583
#15 0x00005555558193ba in sys_excepthook_impl (module=module@entry=<module at remote 0x7ffff78d3770>, exctype=<optimized out>, value=<optimized out>, traceback=<optimized out>) at ./Python/sysmodule.c:738
#16 0x0000555555819422 in sys_excepthook (module=<module at remote 0x7ffff78d3770>, args=0x7fffffffbe70, nargs=<optimized out>) at ./Python/clinic/sysmodule.c.h:73
#17 0x0000555555719d74 in cfunction_vectorcall_FASTCALL (func=<built-in method excepthook of module object at remote 0x7ffff78d3770>, args=0x7fffffffbe70, nargsf=<optimized out>, kwnames=<optimized out>) at Objects/methodobject.c:427
#18 0x00005555556d3231 in _PyObject_VectorcallTstate (tstate=0x555555b378b0 <_PyRuntime+166000>, callable=callable@entry=<built-in method excepthook of module object at remote 0x7ffff78d3770>, args=0x7fffffffbe70, args@entry=0x7fffffffbdf0, nargsf=nargsf@entry=3, kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:92
#19 0x00005555556d332f in _PyObject_FastCallTstate (nargs=3, args=0x7fffffffbdf0, func=<built-in method excepthook of module object at remote 0x7ffff78d3770>, tstate=<optimized out>) at ./Include/internal/pycore_call.h:114
#20 _PyObject_FastCall (func=func@entry=<built-in method excepthook of module object at remote 0x7ffff78d3770>, args=args@entry=0x7fffffffbe70, nargs=nargs@entry=3) at Objects/call.c:308
#21 0x000055555580d1b5 in _PyErr_PrintEx (tstate=0x555555b378b0 <_PyRuntime+166000>, set_sys_last_vars=set_sys_last_vars@entry=1) at Python/pythonrun.c:825
#22 0x000055555580d453 in PyErr_PrintEx (set_sys_last_vars=set_sys_last_vars@entry=1) at Python/pythonrun.c:875
#23 0x000055555580d466 in PyErr_Print () at Python/pythonrun.c:881
#24 0x00007ffff75170ff in pyqt6_err_print() () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#25 0x00007ffff7520c2d in PyQtSlotProxy::unislot(void**) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#26 0x00007ffff7522857 in PyQtSlotProxy::qt_metacall(QMetaObject::Call, int, void**) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#27 0x00007ffff6e1f89d in ?? () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#28 0x00007ffff6e2e16a in QTimer::timeout(QTimer::QPrivateSignal) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#29 0x00007ffff74bd103 in sipQTimer::timerEvent(QTimerEvent*) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#30 0x00007ffff6e1099f in QObject::event(QEvent*) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#31 0x00007ffff749acf3 in sipQTimer::event(QEvent*) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#32 0x00007ffff74d75be in sipQCoreApplication::notify(QObject*, QEvent*) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#33 0x00007ffff6dbffba in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#34 0x00007ffff6f4d1db in QTimerInfoList::activateTimers() () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#35 0x00007ffff7062b3c in ?? () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#36 0x00007ffff6937163 in g_main_context_dispatch () from /usr/lib/libglib-2.0.so.0
#37 0x00007ffff698d9e9 in ?? () from /usr/lib/libglib-2.0.so.0
#38 0x00007ffff69346c5 in g_main_context_iteration () from /usr/lib/libglib-2.0.so.0
#39 0x00007ffff7062e4a in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#40 0x00007ffff6dcc1eb in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#41 0x00007ffff6dc7dae in QCoreApplication::exec() () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/Qt6/lib/libQt6Core.so.6
#42 0x00007ffff745187f in meth_QCoreApplication_exec () from /home/florian/tmp/.venv-retreat/lib/python3.11/site-packages/PyQt6/QtCore.abi3.so
#43 0x000055555571a557 in cfunction_call (func=<built-in method exec of QCoreApplication object at remote 0x7ffff7935f40>, args=(), kwargs=0x0) at Objects/methodobject.c:553
#44 0x00005555556d316e in _PyObject_MakeTpCall (tstate=tstate@entry=0x555555b378b0 <_PyRuntime+166000>, callable=callable@entry=<built-in method exec of QCoreApplication object at remote 0x7ffff7935f40>, args=args@entry=0x7ffff781e078, nargs=<optimized out>, keywords=keywords@entry=0x0) at Objects/call.c:214
#45 0x00005555556d32b1 in _PyObject_VectorcallTstate (tstate=0x555555b378b0 <_PyRuntime+166000>, callable=callable@entry=<built-in method exec of QCoreApplication object at remote 0x7ffff7935f40>, args=args@entry=0x7ffff781e078, nargsf=<optimized out>, kwnames=kwnames@entry=0x0) at ./Include/internal/pycore_call.h:90
#46 0x00005555556d3308 in PyObject_Vectorcall (callable=callable@entry=<built-in method exec of QCoreApplication object at remote 0x7ffff7935f40>, args=args@entry=0x7ffff781e078, nargsf=<optimized out>, kwnames=kwnames@entry=0x0) at Objects/call.c:299
#47 0x00005555557c14d2 in _PyEval_EvalFrameDefault (tstate=0x555555b378b0 <_PyRuntime+166000>, frame=0x7ffff781e020, throwflag=<optimized out>) at Python/ceval.c:4776
#48 0x00005555557c5c81 in _PyEval_EvalFrame (tstate=tstate@entry=0x555555b378b0 <_PyRuntime+166000>, frame=frame@entry=0x7ffff781e020, throwflag=throwflag@entry=0) at ./Include/internal/pycore_ceval.h:66
#49 0x00005555557c5d92 in _PyEval_Vector (tstate=tstate@entry=0x555555b378b0 <_PyRuntime+166000>, func=func@entry=0x7ffff789be30, 
    locals=locals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, args=args@entry=0x0, argcount=argcount@entry=0, kwnames=kwnames@entry=0x0) at Python/ceval.c:6396
#50 0x00005555557c5e9d in PyEval_EvalCode (co=co@entry=<code at remote 0x7ffff7778040>, 
    globals=globals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, 
    locals=locals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}) at Python/ceval.c:1157
#51 0x000055555580aaf4 in run_eval_code_obj (tstate=tstate@entry=0x555555b378b0 <_PyRuntime+166000>, co=co@entry=0x7ffff7778040, 
    globals=globals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, 
    locals=locals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}) at Python/pythonrun.c:1713
#52 0x000055555580abb1 in run_mod (mod=mod@entry=0x555555c1fd30, filename=filename@entry='/home/florian/tmp/repro.py', 
    globals=globals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, 
    locals=locals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, flags=flags@entry=0x7fffffffc9d8, arena=arena@entry=0x7ffff776c640) at Python/pythonrun.c:1734
#53 0x000055555580ac79 in pyrun_file (fp=fp@entry=0x555555b804f0, filename=filename@entry='/home/florian/tmp/repro.py', start=start@entry=257, 
    globals=globals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, 
    locals=locals@entry={'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <SourceFileLoader(name='__main__', path='/home/florian/tmp/repro.py') at remote 0x7ffff773f030>, '__spec__': None, '__annotations__': {}, '__builtins__': <module at remote 0x7ffff78e2ed0>, '__file__': '/home/florian/tmp/repro.py', '__cached__': None, 'QUrl': <PyQt6.sip.wrappertype at remote 0x555555cfee50>, 'QTimer': <PyQt6.sip.wrappertype at remote 0x555555cfd520>, 'QCoreApplication': <PyQt6.sip.wrappertype at remote 0x555555cdd680>, 'app': <QCoreApplication() at remote 0x7ffff7935f40>, 'timer': <QTimer() at remote 0x7ffff4498520>}, closeit=closeit@entry=1, flags=0x7fffffffc9d8) at Python/pythonrun.c:1629
#54 0x000055555580d8cc in _PyRun_SimpleFileObject (fp=fp@entry=0x555555b804f0, filename=filename@entry='/home/florian/tmp/repro.py', closeit=closeit@entry=1, flags=flags@entry=0x7fffffffc9d8) at Python/pythonrun.c:439
#55 0x000055555580da80 in _PyRun_AnyFileObject (fp=fp@entry=0x555555b804f0, filename=filename@entry='/home/florian/tmp/repro.py', closeit=closeit@entry=1, flags=flags@entry=0x7fffffffc9d8) at Python/pythonrun.c:78
#56 0x000055555582b904 in pymain_run_file_obj (program_name=program_name@entry='/home/florian/tmp/.venv-retreat/bin/python3', filename=filename@entry='/home/florian/tmp/repro.py', skip_source_first_line=0) at Modules/main.c:353
#57 0x000055555582ba22 in pymain_run_file (config=config@entry=0x555555b1d910 <_PyRuntime+59600>) at Modules/main.c:372
#58 0x000055555582c191 in pymain_run_python (exitcode=exitcode@entry=0x7fffffffcb34) at Modules/main.c:592
#59 0x000055555582c3e6 in Py_RunMain () at Modules/main.c:671
#60 0x000055555582c460 in pymain_main (args=args@entry=0x7fffffffcb90) at Modules/main.c:701
#61 0x000055555582c52f in Py_BytesMain (argc=<optimized out>, argv=<optimized out>) at Modules/main.c:725
#62 0x0000555555643722 in main (argc=<optimized out>, argv=<optimized out>) at ./Programs/python.c:15

The bounds values in retreat:

(gdb) pp bounds
bounds = 
   autoderefcount="1",[
      ar_start = <int> = {"0"}
      ar_end = <int> = {"2"}
      ar_line = <int> = {"6"}
      opaque = <struct _opaque> = {"{...}"}
   ],<PyCodeAddressRange> = {"{...}"}

Args and locals for tb_displayline:

Details
(gdb) info args
tb = 0x7ffff44aa7b0
f = <_io.StringIO at remote 0x7ffff762b9d0>
filename = '/home/florian/tmp/repro.py'
lineno = 6
frame = Frame 0x7ffff4498600, for file /home/florian/tmp/repro.py, line 6, in <lambda> ()
name = <optimized out>
margin_indent = 0
margin = 0x5555558cc7df ""
(gdb) info locals
line = <optimized out>
res = 0
err = 0
truncation = -4
source_line = 'timer.timeout.connect(lambda: None)'
rc = 0
code_offset = <optimized out>
code = <optimized out>
start_line = 1435344176
end_line = 21845
start_col_byte_offset = 1436689024
end_col_byte_offset = 21845
__PRETTY_FUNCTION__ = "tb_displayline"
start_offset = <optimized out>
end_offset = <optimized out>
left_end_offset = 93824994118249
right_start_offset = -9223372036854775807
primary_error_char = 0x7ffff44ad900 ""
secondary_error_char = 0x10 <error: Cannot access memory at address 0x10>

Your environment

  • CPython versions tested on: 3.11.0b1, current 3.11 branch
  • Operating system and architecture: Arch Linux x86_64

Activity

  1. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    on May 26, 2022
  2. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    3.11only security fixes
    3.12only security fixes
    on May 26, 2022
  3. markshannon commented on May 26, 2022

    @markshannon
    Member

    @The-Compiler can you reproduce this without PyQt6?

    This might be a duplicate of #92597.

  4. The-Compiler commented on May 26, 2022

    @The-Compiler
    ContributorAuthor

    I haven't found a simpler reproducer so far, I'm afraid. Happy to re-test and report once there's a patch for that.

  5. sweeneyde commented on May 27, 2022

    @sweeneyde
    Member

    I replicated something like this by interrupting test_threading with a Ctrl+C, but this was very intermittent and hard to replicate.

    .\python.bat -m test test_threading test_threading test_threading -j0
    Running Debug|x64 interpreter...
    0:00:00 Run tests in parallel using 14 child processes
    
    Kill <TestWorkerProcess #1 running test=test_threading pid=11340 time=4.0 sec>
    
    == Tests result: INTERRUPTED ==
    Test suite interrupted by signal SIGINT.
    
    1 test omitted:
        test_threading
    
    Total duration: 4.1 sec
    Tests result: INTERRUPTED
    Traceback (most recent call last):
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\test\libregrtest\main.py", line 675, in main
        self._main(tests, kwargs)
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\test\libregrtest\main.py", line 729, in _main
        sys.exit(130)
        ^^^^^^^^^^^^^
    SystemExit: 130
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\runpy.py", line 198, in _run_module_as_main
        return _run_code(code, main_globals, None,
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\runpy.py", line 88, in _run_code
        exec(code, run_globals)
        ^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\test\__main__.py", line 2, in <module>
        main()
        ^^^^^^
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\test\libregrtest\main.py", line 737, in main
        Regrtest().main(tests=tests, **kwargs)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\test\libregrtest\main.py", line 669, in main
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "C:\Users\sween\Source\Repos\cpython2\cpython\Lib\contextlib.py", line 141, in __exit__
        def __exit__(self, typ, value, traceback):
    Assertion failed: bounds->ar_start > 0, file C:\Users\sween\Source\Repos\cpython2\cpython\Objects\codeobject.c, line 814
    Fatal Python error: Aborted
    
    Current thread 0x00006854 (most recent call first):
      <no Python frame>
    
    Extension modules: _testcapi (total: 1)
    
  6. kumaraditya303 commented on Jun 7, 2022

    @kumaraditya303
    Contributor

    This is reproducible on Linux with a simple script and interrupting it.

    Script:

    def fibonacci(n):
        if n <=1:
            return n
        return fibonacci(n-1) + fibonacci(n-2)
    
    fibonacci(50)
    python: Objects/codeobject.c:815: retreat: Assertion `bounds->ar_start > 0' failed.
    Aborted (core dumped)
  7. pablogsal commented on Jun 9, 2022

    @pablogsal
    Member

    I can still reproduce this with 3.11.0b3

  8. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    I tried to debug it and it looks like the innermost frame has lasti=0. So I think the exception is raised before anything happened in this frame, or something like this. Where in ceval.c does the KeyboardInterrupt get raised?

  9. markshannon commented on Jun 17, 2022

    @markshannon
    Member

    I'm unable to reproduce this.
    If anyone can reproduce this running under gdb (or equivalent), could you post a traceback, please?

  10. kumaraditya303 commented on Jun 17, 2022

    @kumaraditya303
    Contributor

    I tried to debug it and it looks like the innermost frame has lasti=0. So I think the exception is raised before anything happened in this frame, or something like this. Where in ceval.c does the KeyboardInterrupt get raised?

    handle_signals in ceval.c calls the default interrupt handler which unless overridden raises KeyboardInterrupt in signal_default_int_handler_impl in signalmodule.c.

  11. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    I'm unable to reproduce this.
    If anyone can reproduce this running under gdb (or equivalent), could you post a traceback, please?

    I can reproduce it on a Mac easily with Kumar's fibonacci script. I'll try to run in gdb.

  12. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    Haven't managed to get there with a debugger, but I managed to see this:

    The relevant "goto handle_eval_breaker;" is in the RESUME_QUICK opcode. If I print _PyInterpreterFrame_LASTI(frame); just before, it is indeed 0.

  13. markshannon commented on Jun 17, 2022

    @markshannon
    Member

    _PyInterpreterFrame_LASTI(frame) == 0 should be fine. That just means we are executing the first instruction.

    >>> dis.dis(fibonacci)
      1           0 RESUME                   0
      ...
    
  14. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    So then we call to PyCode_Addr2Location from tb_displayline with addrq=0.

    That calls _PyCode_CheckLineNumber with lasti=0; bounds->ar_start = -1; bounds->ar_end = 0;

    bounds->ar_end <= lasti. so we call _PyLineTable_NextAddressRange(bounds) which bumps bounds to (0,2), and we return to PyCode_Addr2Location (because now bounds->ar_start > lasti is false).

    Then we call retreat() with bound->ar_start == 0, so the assertion fails.

  15. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    If I change the assertion in retreat to assert(bounds->ar_start >= 0); (instead of > 0) then it seems to work.

    After retreat ar_start can be negative, but I put assert(bounds.ar_start >= 0); in PyCode_Addr2Location after advance_with_locations() and that holds.

    Do you remember why the assertion in retreat() has > rather than >=?

  16. added a commit that references this issue on Jun 17, 2022
  17. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    If it's just that the assertion is overly strict, then here's a PR to relax it: #93961

  18. iritkatriel commented on Jun 17, 2022

    @iritkatriel
    Member

    I'm writing a unit test for this, here is how to create such a traceback directly:

    import sys
    import types
    
    def f():
        return sys._getframe()
    
    tb_next = None
    frame = f()
    lasti = 0
    lineno = 2
    tb = types.TracebackType(tb_next, frame, lasti, lineno)
    
    e = KeyboardInterrupt()
    raise e.with_traceback(tb)
    

    Output:

    % ./python.exe sig.py
    Traceback (most recent call last):
      File "/Users/iritkatriel/src/cpython-1/sig.py", line 16, in <module>
        raise e.with_traceback(tb)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/iritkatriel/src/cpython-1/sig.py", line 2, in f
        import sys
    Assertion failed: (bounds->ar_start > 0), function retreat, file codeobject.c, line 815.
    zsh: abort      ./python.exe sig.py
    
  19. markshannon commented on Jun 20, 2022

    @markshannon
    Member

    Do you remember why the assertion in retreat() has > rather than >=

    I don't remember, but looking at the code, it looks like
    bounds->ar_start -= previous_code_delta(bounds); is not safe if the bounds is already pointing to the first entry.
    I think we need to change previous_code_delta to check for bounds->ar_start == 0.

    I think adding this to previous_code_delta should fix it:

    if (bounds->ar_start == 0) {
        // If we looking at the first entry, the "previous" entry has an implicit length of 1.
        return 1;
    }
  20. added a commit that references this issue on Jun 20, 2022
  21. added a commit that references this issue on Jun 20, 2022
  22. added a commit that references this issue on Jun 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

3.11only security fixes3.12only security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)release-blockertype-crashA hard crash of the interpreter, possibly with a core dump

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions