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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
nexedi
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
Hide 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 @@
PyThreadState *tstate; \
PyGILState_STATE state = PyGILState_Ensure(); \
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); \
} \
PyGILState_Release(state); \
...
...
@@ -206,7 +207,8 @@
} \
} else { \
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); \
if (unlikely(ret)) goto_error; \
} \
...
...
@@ -216,7 +218,8 @@
#define __Pyx_TraceLine(lineno, nogil, goto_error) \
if (likely(!__Pyx_use_tracing)); else { \
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); \
if (unlikely(ret)) goto_error; \
} \
...
...
tests/run/line_trace.pyx
View file @
3a8b41ae
...
...
@@ -30,26 +30,73 @@ map_trace_types = {
}.
get
cdef
int
_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
frame
,
traceobj
=
<
object
>
_frame
,
<
object
>
_traceobj
traceobj
.
append
((
map_trace_types
(
what
),
frame
.
f_lineno
-
frame
.
f_code
.
co_firstlineno
))
return
0
cdef
int
trace_trampoline
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
_
arg
)
except
-
1
:
frame
=
<
object
>
_frame
traceobj
=
<
object
>
_traceobj
if
_traceobj
else
None
arg
=
<
object
>
_arg
if
_arg
else
None
cdef
int
_failing_call_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
if
what
==
PyTrace_CALL
:
raise
ValueError
(
"failing call trace!"
)
return
_trace_func
(
_traceobj
,
_frame
,
what
,
arg
)
callback
=
traceobj
else
:
callback
=
frame
.
f_trace
if
callback
is
None
:
return
0
result
=
callback
(
frame
,
what
,
arg
)
frame
.
f_trace
=
result
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!"
)
func
(
frame
,
event
,
arg
)
return
_trace_func
return
_trace_func
def
_create__failing_line_trace_func
(
trace
):
func
=
_create_trace_func
(
trace
)
def
_trace_func
(
frame
,
event
,
arg
):
if
event
==
PyTrace_LINE
and
trace
:
if
trace
and
trace
[
0
]
==
frame
.
f_code
.
co_name
:
# first line in the right function => fail!
raise
ValueError
(
"failing line trace!"
)
cdef
int
_failing_line_trace_func
(
PyObject
*
_traceobj
,
PyFrameObject
*
_frame
,
int
what
,
PyObject
*
arg
)
except
-
1
:
if
what
==
PyTrace_LINE
and
_traceobj
:
frame
,
traceobj
=
<
object
>
_frame
,
<
object
>
_traceobj
if
traceobj
and
traceobj
[
0
]
==
frame
.
f_code
.
co_name
:
# first line in the right function => fail!
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
):
x
=
a
+
b
# 1
...
...
@@ -87,7 +134,7 @@ def run_trace(func, *args):
[('line', 2), ('line', 5), ('return', 5)]
"""
trace
=
[]
PyEval_SetTrace
(
<
Py_tracefunc
>
_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create_trace_func
(
trace
)
)
try
:
func
(
*
args
)
finally
:
...
...
@@ -105,7 +152,7 @@ def fail_on_call_trace(func, *args):
ValueError: failing call trace!
"""
trace
=
[]
PyEval_SetTrace
(
<
Py_tracefunc
>
_failing_call_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create_failing_call_trace_func
(
trace
)
)
try
:
func
(
*
args
)
finally
:
...
...
@@ -142,7 +189,7 @@ def fail_on_line_trace(fail_func):
cdef
int
x
=
1
trace
=
[
'NO ERROR'
]
exception
=
None
PyEval_SetTrace
(
<
Py_tracefunc
>
_failing_line_trace_func
,
trace
)
PyEval_SetTrace
(
<
Py_tracefunc
>
trace_trampoline
,
_create__failing_line_trace_func
(
trace
)
)
try
:
x
+=
1
cy_add
(
1
,
2
)
...
...
@@ -161,3 +208,24 @@ def fail_on_line_trace(fail_func):
else
:
assert
x
==
5
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