You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Traceback says line -1 when KeyboardInterrupt during minimal for-if-loop #107901
More generally, the issue happens with all exceptions raised by other threads.
Run the code below and interrupt with ctrl+c.
# If part of a file, potentially more code before the loop. Traceback says -1 regardless.foriinrange(30000000):
ifnoti%1000000:
pass# Or any other operation here that is faster than iterating a million i values.
The issue persists whether running from the shell or as a file or even using exec. It works the same inside functions/methods. It exists in 3.11 and 3.12 but not 3.10, across Windows and Linux.
CPython versions tested on: 3.10.6 (no issue), 3.11.1 (issue), 3.11.4 (issue), 3.12.0rc1 (issue)
Operating system and architecture: Windows 10 and Ubuntu 22.04.2 LTS (WSL)
I assume we need every instruction that checks the eval breaker to also have a line number. It looks like propagate_line_numbers and duplicate_exits_without_lineno try to enforce something like this, but then normalize_jumps re-introduces an instruction with NO_LOCATION.
Here's the disassembly showing a JUMP_BACKWARD with Positions(lineno=None, end_lineno=None, col_offset=None, end_col_offset=None):
Looks plausible. It might be simply a matter of copying the location of the old (backward jump) to the new jump that we are adding in this line. Let me know if you would like to try, or would prefer I do.
Does the insertion of the extra jump take place before or after line number propagation?
If it happens before, then simply copying the line number may not be insufficient, as the original jump may not have a line number.
This also happens in 3.11, which suggests that 4c72517 is not the root cause.
I think line number propagation (or the lack of) is the issue.
For the fix in 3.13 we might want to tag instructions that check the eval breaker (as well as raises and returns) as needing a line number, then make sure we propagate line numbers to those instructions.
For the 3.11 and 3.12 maybe just backport the change to line propagation and not the metadata?
Does the insertion of the extra jump take place before or after line number propagation?
If it happens before, then simply copying the line number may not be insufficient, as the original jump may not have a line number.
I created a PR that fixes the case that was reported here.
We will need to follow up with tests that ensure that all instructions that check the eval breaker have a line number. I tested and found that this is not the case, I saw some instructions in exception handlers that violated this (and they were not as straightforward to fix).
Activity
sunmy2019 commentedon Aug 13, 2023
@markshannon as an expert here.
I investigated the
-1being set at Line 950 here.cpython/Objects/codeobject.c
Lines 944 to 955 in ee40b3e
-1set atduring the call of
Also the disassembly here:
sweeneyde commentedon Aug 13, 2023
cc @iritkatriel as well. I bisected to 4c72517, and I think this is the relevant line:
cpython/Python/flowgraph.c
Line 534 in ee40b3e
I assume we need every instruction that checks the eval breaker to also have a line number. It looks like
propagate_line_numbersandduplicate_exits_without_linenotry to enforce something like this, but thennormalize_jumpsre-introduces an instruction withNO_LOCATION.Here's the disassembly showing a
JUMP_BACKWARDwithPositions(lineno=None, end_lineno=None, col_offset=None, end_col_offset=None):Disassembly of reproducer on main.
pan324 commentedon Aug 13, 2023
In case this helps with debugging, I've played around a bit more and found an even simpler test case:
sunmy2019 commentedon Aug 13, 2023
Agree.
iritkatriel commentedon Aug 13, 2023
Looks plausible. It might be simply a matter of copying the location of the old (backward jump) to the new jump that we are adding in this line. Let me know if you would like to try, or would prefer I do.
markshannon commentedon Aug 14, 2023
Does the insertion of the extra jump take place before or after line number propagation?
If it happens before, then simply copying the line number may not be insufficient, as the original jump may not have a line number.
markshannon commentedon Aug 14, 2023
This also happens in 3.11, which suggests that 4c72517 is not the root cause.
I think line number propagation (or the lack of) is the issue.
For the fix in 3.13 we might want to tag instructions that check the eval breaker (as well as raises and returns) as needing a line number, then make sure we propagate line numbers to those instructions.
For the 3.11 and 3.12 maybe just backport the change to line propagation and not the metadata?
iritkatriel commentedon Aug 21, 2023
It happens after line numbers are resolved.
iritkatriel commentedon Aug 21, 2023
I created a PR that fixes the case that was reported here.
We will need to follow up with tests that ensure that all instructions that check the eval breaker have a line number. I tested and found that this is not the case, I saw some instructions in exception handlers that violated this (and they were not as straightforward to fix).
gh-107901: Fix missing line number on BACKWARD_JUMP at the end of a f…
23 remaining items
pythongh-107901: compiler replaces POP_BLOCK instruction by NOPs befo…
gh-107901: compiler replaces POP_BLOCK instruction by NOPs before opt…
pythongh-107901: make compiler inline basic blocks with no line numbe…
gh-107901: make compiler inline basic blocks with no line number and …
pythongh-107901: synthetic jumps which are not at end of loop no long…
pythongh-107901: jump leaving an exception handler doesn't need an ev…
pythongh-107901: duplicate blocks with no lineno that have an eval br…
pythongh-107901: compiler replaces POP_BLOCK instruction by NOPs befo…
pythongh-107901: make compiler inline basic blocks with no line numbe…
pythongh-107901: make compiler inline basic blocks with no line numbe…
pythongh-107901: synthetic jumps which are not at end of loop no long…
pythongh-107901: jump leaving an exception handler doesn't need an ev…
pythongh-107901: duplicate blocks with no lineno that have an eval br…
pythongh-107901: compiler replaces POP_BLOCK instruction by NOPs befo…