Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cython
Commits
3a8b41ae
Commit
3a8b41ae
authored
Sep 01, 2017
by
scoder
Committed by
GitHub
Sep 01, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1774 from traff/master
Fix "NoneType object is not callable" exception when using a tracing …
parents
8ecf2e96
bcb676e0
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
92 additions
and
21 deletions
+92
-21
Cython/Utility/Profile.c
Cython/Utility/Profile.c
+6
-3
tests/run/line_trace.pyx
tests/run/line_trace.pyx
+86
-18
No files found.
Cython/Utility/Profile.c
View file @
3a8b41ae
...
@@ -198,7 +198,8 @@
...
@@ -198,7 +198,8 @@
PyThreadState *tstate; \
PyThreadState *tstate; \
PyGILState_STATE state = PyGILState_Ensure(); \
PyGILState_STATE state = PyGILState_Ensure(); \
tstate = __Pyx_PyThreadState_Current; \
tstate = __Pyx_PyThreadState_Current; \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc)) { \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
} \
} \
PyGILState_Release(state); \
PyGILState_Release(state); \
...
@@ -206,7 +207,8 @@
...
@@ -206,7 +207,8 @@
} \
} \
} else { \
} else { \
PyThreadState* tstate = __Pyx_PyThreadState_Current; \
PyThreadState* tstate = __Pyx_PyThreadState_Current; \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc)) { \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
if (unlikely(ret)) goto_error; \
if (unlikely(ret)) goto_error; \
} \
} \
...
@@ -216,7 +218,8 @@
...
@@ -216,7 +218,8 @@
#define __Pyx_TraceLine(lineno, nogil, goto_error) \
#define __Pyx_TraceLine(lineno, nogil, goto_error) \
if (likely(!__Pyx_use_tracing)); else { \
if (likely(!__Pyx_use_tracing)); else { \
PyThreadState* tstate = __Pyx_PyThreadState_Current; \
PyThreadState* tstate = __Pyx_PyThreadState_Current; \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc)) { \
if (unlikely(tstate->use_tracing && tstate->c_tracefunc \
&& __pyx_frame->f_trace != Py_None)) { \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
int ret = __Pyx_call_line_trace_func(tstate, $frame_cname, lineno); \
if (unlikely(ret)) goto_error; \
if (unlikely(ret)) goto_error; \
} \
} \
...
...
tests/run/line_trace.pyx
View file @
3a8b41ae
...
@@ -30,26 +30,73 @@ map_trace_types = {
...
@@ -30,26 +30,73 @@ map_trace_types = {
}.
get
}.
get
cdef
int
_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
cdef
int
trace_trampoline
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
_arg
)
except
-
1
:
frame
,
traceobj
=
<
object
>
_frame
,
<
object
>
_traceobj
frame
=
<
object
>
_frame
traceobj
.
append
((
map_trace_types
(
what
),
frame
.
f_lineno
-
frame
.
f_code
.
co_firstlineno
))
traceobj
=
<
object
>
_traceobj
if
_traceobj
else
None
arg
=
<
object
>
_arg
if
_arg
else
None
if
what
==
PyTrace_CALL
:
callback
=
traceobj
else
:
callback
=
frame
.
f_trace
if
callback
is
None
:
return
0
return
0
result
=
callback
(
frame
,
what
,
arg
)
cdef
int
_failing_call_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
frame
.
f_trace
=
result
if
what
==
PyTrace_CALL
:
if
result
is
None
:
PyEval_SetTrace
(
NULL
,
None
)
return
0
else
:
return
0
def
_create_trace_func
(
trace
):
def
_trace_func
(
frame
,
event
,
arg
):
trace
.
append
((
map_trace_types
(
event
),
frame
.
f_lineno
-
frame
.
f_code
.
co_firstlineno
))
return
_trace_func
return
_trace_func
def
_create_failing_call_trace_func
(
trace
):
func
=
_create_trace_func
(
trace
)
def
_trace_func
(
frame
,
event
,
arg
):
if
event
==
PyTrace_CALL
:
raise
ValueError
(
"failing call trace!"
)
raise
ValueError
(
"failing call trace!"
)
return
_trace_func
(
_traceobj
,
_frame
,
what
,
arg
)
func
(
frame
,
event
,
arg
)
return
_trace_func
return
_trace_func
cdef
int
_failing_line_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
def
_create__failing_line_trace_func
(
trace
):
if
what
==
PyTrace_LINE
and
_traceobj
:
func
=
_create_trace_func
(
trace
)
frame
,
traceobj
=
<
object
>
_frame
,
<
object
>
_traceobj
def
_trace_func
(
frame
,
event
,
arg
):
if
traceobj
and
traceobj
[
0
]
==
frame
.
f_code
.
co_name
:
if
event
==
PyTrace_LINE
and
trace
:
if
trace
and
trace
[
0
]
==
frame
.
f_code
.
co_name
:
# first line in the right function => fail!
# first line in the right function => fail!
raise
ValueError
(
"failing line trace!"
)
raise
ValueError
(
"failing line trace!"
)
return
_trace_func
(
_traceobj
,
_frame
,
what
,
arg
)
func
(
frame
,
event
,
arg
)
return
_trace_func
return
_trace_func
def
_create_disable_tracing
(
trace
):
func
=
_create_trace_func
(
trace
)
def
_trace_func
(
frame
,
event
,
arg
):
if
frame
.
f_lineno
-
frame
.
f_code
.
co_firstlineno
==
2
:
return
None
func
(
frame
,
event
,
arg
)
return
_trace_func
return
_trace_func
def
cy_add
(
a
,
b
):
def
cy_add
(
a
,
b
):
x
=
a
+
b
# 1
x
=
a
+
b
# 1
...
@@ -87,7 +134,7 @@ def run_trace(func, *args):
...
@@ -87,7 +134,7 @@ def run_trace(func, *args):
[('line', 2), ('line', 5), ('return', 5)]
[('line', 2), ('line', 5), ('return', 5)]
"""
"""
trace
=
[]
trace
=
[]
PyEval_SetTrace
(
<
Py_tracefunc
>
_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create_trace_func
(
trace
)
)
try
:
try
:
func
(
*
args
)
func
(
*
args
)
finally
:
finally
:
...
@@ -105,7 +152,7 @@ def fail_on_call_trace(func, *args):
...
@@ -105,7 +152,7 @@ def fail_on_call_trace(func, *args):
ValueError: failing call trace!
ValueError: failing call trace!
"""
"""
trace
=
[]
trace
=
[]
PyEval_SetTrace
(
<
Py_tracefunc
>
_failing_call_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create_failing_call_trace_func
(
trace
)
)
try
:
try
:
func
(
*
args
)
func
(
*
args
)
finally
:
finally
:
...
@@ -142,7 +189,7 @@ def fail_on_line_trace(fail_func):
...
@@ -142,7 +189,7 @@ def fail_on_line_trace(fail_func):
cdef
int
x
=
1
cdef
int
x
=
1
trace
=
[
'NO ERROR'
]
trace
=
[
'NO ERROR'
]
exception
=
None
exception
=
None
PyEval_SetTrace
(
<
Py_tracefunc
>
_failing_line_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create__failing_line_trace_func
(
trace
)
)
try
:
try
:
x
+=
1
x
+=
1
cy_add
(
1
,
2
)
cy_add
(
1
,
2
)
...
@@ -161,3 +208,24 @@ def fail_on_line_trace(fail_func):
...
@@ -161,3 +208,24 @@ def fail_on_line_trace(fail_func):
else
:
else
:
assert
x
==
5
assert
x
==
5
return
trace
return
trace
def
disable_trace
(
func
,
*
args
):
"""
>>> def py_add(a,b):
... x = a+b
... return x
>>> disable_trace(py_add, 1, 2)
[('call', 0), ('line', 1)]
>>> disable_trace(cy_add, 1, 2)
[('call', 0), ('line', 1)]
>>> disable_trace(cy_add_with_nogil, 1, 2)
[('call', 0), ('line', 1)]
"""
trace
=
[]
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create_disable_tracing
(
trace
))
try
:
func
(
*
args
)
finally
:
PyEval_SetTrace
(
NULL
,
None
)
return
trace
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment