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

atexit does not work in python-jl #208

Closed
tkf opened this issue Oct 24, 2018 · 3 comments · Fixed by JuliaPy/PyCall.jl#603
Closed

atexit does not work in python-jl #208

tkf opened this issue Oct 24, 2018 · 3 comments · Fixed by JuliaPy/PyCall.jl#603
Assignees

Comments

@tkf
Copy link
Member

tkf commented Oct 24, 2018

$ python -c 'from atexit import register; register(lambda: print("hello"))'
hello

$ python-jl -c 'from atexit import register; register(lambda: print("hello"))'
@tkf
Copy link
Member Author

tkf commented Oct 27, 2018

Just calling Py_Finalize forces Python to call atexit.register hook:

diff --git a/julia/python_jl.py b/julia/python_jl.py
index 5f4aad5..dc63a0a 100644
--- a/julia/python_jl.py
+++ b/julia/python_jl.py
@@ -40,6 +40,7 @@ import PyCall
 PyCall.pyimport("julia")[:Julia](init_julia=false)

 let code = PyCall.pyimport("julia.pseudo_python_cli")[:main](ARGS)
+    ccall(PyCall.@pysym(:Py_Finalize), Cvoid, ())
     if code isa Integer
         exit(code)
     end

But it produces a segfault because PyCall has a bunch of references to PyObjects which are now pointing nowhere. (Maybe the problem with multiprocessing #206 (comment) also is relevant to this?)

$ python-jl -c 'from atexit import register; register(lambda: print("hello"))'
hello

signal (11): Segmentation fault
in expression starting at no file:0
unknown function (ip: 0x7f48dcadd971)
pydecref_ at /home/takafumi/.julia/dev/PyCall/src/PyCall.jl:102 [inlined]
pydecref at /home/takafumi/.julia/dev/PyCall/src/PyCall.jl:107
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2184
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1537 [inlined]
run_finalizer at /buildworker/worker/package_linux64/build/src/gc.c:115
jl_gc_run_finalizers_in_list at /buildworker/worker/package_linux64/build/src/gc.c:210
jl_gc_run_all_finalizers at /buildworker/worker/package_linux64/build/src/gc.c:245
jl_atexit_hook at /buildworker/worker/package_linux64/build/src/init.c:260
unknown function (ip: 0x40151c)
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
unknown function (ip: 0x4015b4)
Allocations: 11921591 (Pool: 11918737; Big: 2854); GC: 25

@stevengj
Copy link
Member

PyCall could probably check if Python is finalizing before calling decref?

@tkf
Copy link
Member Author

tkf commented Oct 28, 2018

Yeah, I was thinking something like

const _finalized = Ref(false)

function Py_Finalize()
    # maybe clear pycall_gc (how?)
    _finalized[] = true
    ccall(@pysym(:Py_Finalize), Cvoid, ())
end

function pydecref_(o::Union{PyPtr,PyObject})
    if _finalized[]
        return
    end
    ccall(@pysym(:Py_DecRef), Cvoid, (PyPtr,), o)
end

function __init__()
    ...
    atexit(Py_Finalize)  # or maybe not...
end

But I haven't checked if it works.

tkf added a commit to tkf/PyCall.jl that referenced this issue Oct 28, 2018
stevengj pushed a commit to JuliaPy/PyCall.jl that referenced this issue Nov 4, 2018
* Avoid segfault during exit process

closes JuliaPy/pyjulia#208

* Support Julia 0.6

* Revert back pydecref_ return type

* shorten code slightly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants