This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Lineno calculation sometimes broken
Type: Stage:
Components: Interpreter Core Versions: Python 2.3
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mwh Nosy List: arigo, glchapman, mwh, nnorwitz, tim.peters
Priority: normal Keywords:

Created on 2003-03-24 17:09 by glchapman, last changed 2022-04-10 16:07 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
for-set-lineno.diff mwh, 2003-03-24 17:43
Messages (10)
msg15242 - (view) Author: Greg Chapman (glchapman) Date: 2003-03-24 17:09
I'm running the win32 version of Python 2.3a2.  I ran into 
this when I got a traceback pointing to a wrong 
linenumber.  It also messes up debugging in 
Pythonwin.  Anyway, you can see from the disassembly 
below that something goes seriously amiss when the 
code reaches the FOR_ITER:


>>> import httplib
>>> import dis
>>> dis.dis(httplib.HTTPConnection.connect)
524           0 LOAD_CONST

              3 STORE_FAST

525           6 SETUP_LOOP
              9 LOAD_GLOBAL
             12 LOAD_ATTR
             15 LOAD_FAST
             18 LOAD_ATTR
             21 LOAD_FAST
             24 LOAD_ATTR
             27 LOAD_CONST

526          30 LOAD_GLOBAL
             33 LOAD_ATTR
             36 CALL_FUNCTION
             39 GET_ITER

781     >>   40 FOR_ITER
msg15243 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-03-24 17:16
Logged In: YES 
user_id=6656

yow!  probably my fault.
msg15244 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-03-24 17:36
Logged In: YES 
user_id=6656

Waddya know, it's not my fault.

For some reason, something is trying to store a negative
line_incr into the c_lnotab which gets masked into a line
increment of 255.  Fun.
msg15245 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-03-24 17:43
Logged In: YES 
user_id=6656

Stupid minimal testcase:

def f():
    for res in range(1,
                     10):
        pass

Tim, you've looked at compile.c today <wink>, can you check
the attached patch?
msg15246 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2003-03-29 23:38
Logged In: YES 
user_id=33168

The patch worked for me on Linux, after I removed
httplib.pyc. :-)
Does it jump to the right line in the debugger whe iterating
through a loop?
msg15247 - (view) Author: Tim Peters (tim.peters) * (Python committer) Date: 2003-04-28 20:57
Logged In: YES 
user_id=31435

Well, this one's a mess.  The patch changes debugger 
behavior in that it no longer stops on the 'for' each time 
around the loop.  I had better luck leaving the com_set_lineno
() call where it is now, but changing its second argument 
instead, like so:

	com_set_lineno(c, c->c_last_line);

Then it stops on the "for" each time around the loop, but 
pointing at the last line of the "for" (in your whittled example, 
on the line ending with "10):").  Better than nothing.

Unfortunately, the encoding of lnotab assumes that line 
numbers and byte offsets are presented in monotonically non-
decreasing order.
msg15248 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-04-29 11:40
Logged In: YES 
user_id=6656

> Well, this one's a mess.

Hadn't noticed that <wink>.

I had become aware that my patch wasn't the right answer. 
I'll try your idea when cvs up finishes...

> Unfortunately, the encoding of lnotab assumes that line 
> numbers and byte offsets are presented in monotonically 
> non-decreasing order.

Presumably this *could* change, if we were sufficiently
motivated.
msg15249 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-04-29 17:08
Logged In: YES 
user_id=6656

Used Tim's idea on compile.c.

Knocked test_dis about a bit to include this case, and make
it *slightly* less rampantly fragile.

Python/compile.c revision 2.282
Lib/test/test_trace.py revision 1.3
msg15250 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2003-04-29 18:41
Logged In: YES 
user_id=4771

Someone motivated could go ahead and allow for ranges of
bytecodes to be mapped to *ranges* of line numbers instead
of to just a single line. The debugger would then display
all the lines in the range. The result would be more natural
when single-stepping through multiline statements.

It would also give a clean fix to several problems beside
the one discussed here, e.g. the final POP_TOP of an
if/then/else being mapped to the last line of the 'else'
part, but being reached when the 'then' branch is taken.
This currently works as expected because the line trace hook
is only fired when we reach the first opcode of a range, not
when we jump in the middle of a range -- which is a hack
because it is the cause of Michael's patch not stopping on
the 'for' after each iteration.

I may be the aforementioned motivated person if the solution
seems worthwhile to try :-)
msg15251 - (view) Author: Michael Hudson (mwh) (Python committer) Date: 2003-04-30 08:29
Logged In: YES 
user_id=6656

It has struck me before that some CS type must have thought
about efficient ways of mapping intervals into some domain.

There are quite a few warts here -- for example given

1: f(parm1,
2:   parm2,
3:   parm3)

if the body of f raises an exception, the traceback points
at line 3.
That's always annoyed me.

At any rate, if you're prepared to think about this, don't
let me be the one to stop you!
History
Date User Action Args
2022-04-10 16:07:52adminsetgithub: 38209
2003-03-24 17:09:37glchapmancreate