Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use disable_sigint instead of sigatomic_(begin|end) #686

Merged
merged 3 commits into from
May 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions src/PyCall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,6 @@ if isdefined(Base, :hasproperty) # Julia 1.2
import Base: hasproperty
end

# Python C API is not interrupt-safe. In principle, we should
# use sigatomic for every ccall to the Python library, but this
# should really be fixed in Julia (#2622). However, we will
# use the sigatomic_begin/end functions to protect pycall and
# similar long-running (or potentially long-running) code.
import Base: sigatomic_begin, sigatomic_end

import Conda
import MacroTools # because of issue #270
import Base.Iterators: filter
Expand Down
16 changes: 13 additions & 3 deletions src/exception.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,18 @@ callsym(s::QuoteNode) = s.value
import Base.Meta.isexpr
callsym(ex::Expr) = isexpr(ex,:macrocall,2) ? callsym(ex.args[2]) : isexpr(ex,:ccall) ? callsym(ex.args[1]) : ex

"""
_handle_error(msg)

Throw a PyError if available, otherwise throw ErrorException.
This is a hack to manually do the optimization described in
https://github.com/JuliaLang/julia/issues/29688
"""
@noinline function _handle_error(msg)
pyerr_check(msg)
error(msg, " failed")
end

# Macros for common pyerr_check("Foo", ccall((@pysym :Foo), ...)) pattern.
macro pycheck(ex)
:(pyerr_check($(string(callsym(ex))), $(esc(ex))))
Expand All @@ -80,9 +92,7 @@ macro pycheckv(ex, bad)
quote
val = $(esc(ex))
if val == $(esc(bad))
# throw a PyError if available, otherwise throw ErrorException
pyerr_check($(string(callsym(ex))))
error($(string(callsym(ex))), " failed")
_handle_error($(string(callsym(ex))))
end
val
end
Expand Down
18 changes: 8 additions & 10 deletions src/pyeval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,15 @@ pynamespace(m::Module) =
# and a current "file name" to use for stack traces
function pyeval_(s::AbstractString, globals=pynamespace(Main), locals=pynamespace(Main),
input_type=Py_eval_input, fname="PyCall")
sigatomic_begin()
try
o = PyObject(@pycheckn ccall((@pysym :Py_CompileString), PyPtr,
(Cstring, Cstring, Cint),
s, fname, input_type))
return PyObject(@pycheckn ccall((@pysym :PyEval_EvalCode),
PyPtr, (PyPtr, PyPtr, PyPtr),
o, globals, locals))
finally
sigatomic_end()
o = PyObject(@pycheckn ccall((@pysym :Py_CompileString), PyPtr,
(Cstring, Cstring, Cint),
s, fname, input_type))
ptr = disable_sigint() do
@pycheckn ccall((@pysym :PyEval_EvalCode),
PyPtr, (PyPtr, PyPtr, PyPtr),
o, globals, locals)
end
return PyObject(ptr)
end

"""
Expand Down
5 changes: 1 addition & 4 deletions src/pyfncall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,11 @@ Sets `ret.o` to the result of the call, and returns `ret::PyObject`.
"""
function __pycall!(ret::PyObject, pyargsptr::PyPtr, o::Union{PyObject,PyPtr},
kw::Union{Ptr{Cvoid}, PyObject})
sigatomic_begin()
try
disable_sigint() do
retptr = @pycheckn ccall((@pysym :PyObject_Call), PyPtr, (PyPtr,PyPtr,PyPtr), o,
pyargsptr, kw)
pydecref_(ret)
setfield!(ret, :o, retptr)
finally
sigatomic_end()
end
return ret #::PyObject
end
Expand Down
10 changes: 2 additions & 8 deletions src/pyiterator.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,11 @@

Base.IteratorSize(::Type{PyObject}) = Base.SizeUnknown()
function _start(po::PyObject)
sigatomic_begin()
try
disable_sigint() do
o = PyObject(@pycheckn ccall((@pysym :PyObject_GetIter), PyPtr, (PyPtr,), po))
nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), o))

return (nxt,o)
finally
sigatomic_end()
end
end

Expand Down Expand Up @@ -76,12 +73,9 @@ _start(piter::PyIterator) = _start(piter.o)

function Base.iterate(piter::PyIterator{T}, s=_start(piter)) where {T}
ispynull(s[1]) && return nothing
sigatomic_begin()
try
disable_sigint() do
nxt = PyObject(@pycheck ccall((@pysym :PyIter_Next), PyPtr, (PyPtr,), s[2]))
return (convert(T,s[1]), (nxt, s[2]))
finally
sigatomic_end()
end
end
function Base.iterate(po::PyObject, s=_start(po))
Expand Down