Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
fix #562, bug in reviving objects when WeakRefs are cleared earlier
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed Mar 9, 2021
1 parent 52d2f73 commit b349b20
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions src/GLib/gtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ gc_unref(x::Ptr{GObject}) = ccall((:g_object_unref, libgobject), Nothing, (Ptr{G
const gc_preserve_glib = Dict{Union{WeakRef, GObject}, Bool}() # glib objects
const gc_preserve_glib_lock = Ref(false) # to satisfy this lock, must never decrement a ref counter while it is held
const topfinalizer = Ref(true) # keep recursion to a minimum by only iterating from the top
const await_finalize = Any[]
const await_finalize = Set{Any}()

Base.isequal(x::GObject, w::WeakRef) = x === w.value # cuts the number of MethodInstances from O(N^2) to O(N)

Expand Down Expand Up @@ -424,12 +424,20 @@ function gobject_ref(x::T) where T <: GObject
gc_preserve_glib_lock[] = true
strong = get(gc_preserve_glib, x, nothing)
if strong === nothing
# we haven't seen this before, setup the metadata
deref = @cfunction(gc_unref, Nothing, (Ref{T},))
ccall((:g_object_set_qdata_full, libgobject), Nothing,
(Ptr{GObject}, UInt32, Any, Ptr{Nothing}), x, jlref_quark::UInt32, x,
deref) # add a circular reference to the Julia object in the GObject
addref(Ref{GObject}(x)[])
if ccall((:g_object_get_qdata, libgobject), Ptr{Cvoid},
(Ptr{GObject}, UInt32), x, jlref_quark::UInt32) != C_NULL
# have set up metadata for this before, but its weakref has been cleared. restore the ref.
delete!(await_finalize, x)
finalizer(delref, x)
gc_preserve_glib[WeakRef(x)] = false # record the existence of the object, but allow the finalizer
else
# we haven't seen this before, setup the metadata
deref = @cfunction(gc_unref, Nothing, (Ref{T},))
ccall((:g_object_set_qdata_full, libgobject), Nothing,
(Ptr{GObject}, UInt32, Any, Ptr{Nothing}), x, jlref_quark::UInt32, x,
deref) # add a circular reference to the Julia object in the GObject
addref(Ref{GObject}(x)[])
end
elseif strong
# oops, we previously deleted the link, but now it's back
addref(Ref{GObject}(x)[])
Expand Down

0 comments on commit b349b20

Please sign in to comment.