-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
SegFault in PyCall
#11395
Comments
This is the farthest I could reduce now. using PyCall
# Othe module does not produce the same error since there's no `True_`
o = pyimport("numpy")
mems = PyCall.pycall(PyCall.inspect["getmembers"], PyCall.PyObject, o)
# Do not call convert -- No SegFault
convert(Vector{Tuple{AbstractString, PyCall.PyObject}}, mems)
# Do not create a new bareodule -- No SegFault
m = Module(:pyimport)
# Do not create nested module -- No SegFault
m = eval(m, Expr(:toplevel,
Expr(:module, false, :__anon__, Expr(:block)),
:__anon__))
function convert2(o::PyObject)
try
info = PyCall.PyArray_Info(o)
println(1)
try
println(2)
copy(PyCall.PyArray{Bool, length(info.sz)}(o, info))
catch
println(3)
end
catch
error()
PyCall.py2array(Bool, o)
end
end
# Do not convert any of the following python object -- No SegFault
convert2(o["True_"])
copy(PyDict{PyAny, PyAny}(o["__builtins__"]))
# Change to global value assignment -- No SegFault
eval(m, :(f(s) = 0)) |
@garrison OK good, that is actually what I'm going to do next. |
I am suspicious that 18fa555 might have led to the problem, but my bisecting is not yet conclusive. |
My bisect in the end identified 63849fd as the first bad commit. That's not to say that the problem didn't start sooner, as there were commits I almost marked as "good" because |
I'm not bisecting now and will probably not be doing that until this weekend. |
It probably shouldn't be causing Julia to segfault, but on 0.4 you can now construct an anonymous bare module directly instead of using that ugly hack. |
This is probably GC related. turning off gc before |
This looks like a missing root and it is indeed where the SegFault'd pointer was allocated. However, rooting it here didn't help... |
@yuyichao when you link to lines of code, be sure to hit |
@tkelman Thanks for the tip. I always manually find the file in the commit when I want to do that and that's why I only do it when I think it worth keeping for a long time. Will do that from now on =) This is sth related to typeinference and GC using PyCall
# Othe module does not produce the same error since there's no `True_`
gc()
# Do not create a new bareodule -- No SegFault
m = Module(:pyimport)
gc()
# Do not create nested module -- No SegFault
m = eval(m, Expr(:toplevel,
Expr(:module, false, :__anon__, Expr(:block)),
:__anon__))
gc()
function PyObject2()
PyObject(p, [true])
end
gc()
gc()
precompile(PyObject2, ())
gc()
eval(m, :(f(s) = 0))
ccall(:jl_gc_disable, Void, ()) When I watch the pointer that got a segfault, it does get assigned multiple times in typeinf although I was too lazy to track the generated code..... |
Note that in the above example, none of the |
Repro without
|
m = Module(:_import)
m = eval(m, Expr(:toplevel,
Expr(:module, false, :__anon__, Expr(:block)),
:__anon__))
# Very likely the overridden `m = Module(:_import)` got leaked here
# Assign the `__anon__` module to another variable surpresses the SegFault
# Although it doesn't trigger a SegFault without calling `precompile` below
gc()
precompile(Base.withenv, (Function, Pair{ASCIIString, ASCIIString}))
eval(m, :(f(s) = 0)) |
Is the child module holding a reference to the parent module? (In GC sense) |
Yes but modules are treated specially in gc and the parent module is not marked here. I'll push a fix this is wrong. Thanks for finding this ! (as well as the missing root w/ add_std_imports). |
The module part might be special cases but the deserializeing part looks strange for me... |
And maybe the deserializing part is related to #11397 ? |
(1) and (2) don't need a wb since expr was just created. It does not matter that much in this case but well. |
#11397 is using the julia serializer, not the dump.c one |
Also a missing root for new modules. Thanks to @yuyiacho for finding those issues. Fix #11395.
@carnaval Thnks for the explaination. That makes sense. |
Confirmed that my final repro and |
Also a missing root for new modules. Thanks to @yuyichao for finding those issues. Fix JuliaLang#11395.
Also a missing root for new modules. Thanks to @yuyichao for finding those issues. Fix JuliaLang#11395.
See comments in JuliaPy/PyCall.jl#144
Reproduce with
PyCall
, run the following script or run in REPL without the printing.The PR (JuliaPy/PyCall.jl#144) is required to make
PyCall
working.GC_VERIFY
didn't pick up anything.I am having a hard time removing the
PyCall
dependency for reproducing it this time since it is too big (might still try though...). It is not clear whether this is aPyCall.jl
bug or ajulia
bug but since the crash is in not in python I suspect it is julia...The text was updated successfully, but these errors were encountered: