classification
Title: frame.f_lineno doesn't get updated after local trace function assigned to it
Type: behavior Stage: needs patch
Components: Interpreter Core Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: eggy, jcea, ncoghlan, xdegaye, ysj.ray
Priority: normal Keywords:

Created on 2009-10-29 17:16 by eggy, last changed 2013-02-25 17:45 by jcea.

Files
File name Uploaded Description Edit
tracer_testcase.py eggy, 2009-10-29 17:16
Messages (3)
msg94681 - (view) Author: Mark Florisson (eggy) * Date: 2009-10-29 17:16
As you can see, when a local trace function sets f_lineno, f_lineno 
doesn't get updated on subsequent lines. Otherwise it works fine.
$ python tracer_testcase.py                                                                                                                      
12
12
12

13
14
15

The reference manual (for python 2.6) states the following: "f_lineno is 
the current line number of the frame — writing to this from within a 
trace function jumps to the given line (only for the bottom-most frame). 
A debugger can implement a Jump command (aka Set Next Statement) by 
writing to f_lineno.". This is contradictory with the shown results, 
because apparently it doesn't always represent the current line number.
msg122279 - (view) Author: ysj.ray (ysj.ray) Date: 2010-11-24 14:08
It's not a bug. What happens is like this:

1, You set trace function using sys.settrace(tracer).
2, When the following func() is called, tracer is called with a "call" event, so the trace function in PyThreadState is set to NULL since "sys.settrace(None)" is execute, but since the return value is a valid local trace function, the frame of called function("func()") has its local trace function.
3, The called function("func()") executes, though its frame has a local trace function, but it will not be executed since PyThreadState->c_tracefunc is NULL. When you get f_lineno from frame, you get the not refreshed f_lineno value but not the dynamically computed lineno, as the f_lineno's getter function said:
    if(f->f_trace)
        return f->f_lineno;
    else
        return PyCode_Addr2Line(f->f_code, f->f_lasti);

   Here because your frame's local trace function is not executed, the f_lineno is not refreshed.

4, When the second time func() calls, there is no global trace function. Each time you get the f_lineno, it uses PyCode_Addr2Line() to get the dynamically computed line number.


I think this situation is so rarely that the doc saying "f_lineno is 
the current line number of the frame" is correct.
msg175969 - (view) Author: Xavier de Gaye (xdegaye) * (Python triager) Date: 2012-11-19 21:05
See also the related issue 16482.
History
Date User Action Args
2013-02-25 17:45:17jceasetnosy: + jcea
2012-11-19 21:05:45xdegayesetnosy: + xdegaye
messages: + msg175969
2011-11-29 06:20:35ezio.melottisetnosy: + ncoghlan

versions: + Python 3.3, - Python 3.1
2010-11-24 14:08:08ysj.raysetnosy: + ysj.ray
messages: + msg122279
2010-07-11 10:10:47BreamoreBoysetstage: needs patch
versions: - Python 2.6, Python 2.5, Python 2.4, Python 3.0
2009-10-29 17:16:57eggycreate