From 52d81b037a25799ac7a93415c70edb1c991bb421 Mon Sep 17 00:00:00 2001 From: Lyndon White Date: Tue, 21 Nov 2017 23:57:06 +0800 Subject: [PATCH] Finalizers take function as first argument (closes #16307) (#24605) make finalizers take function as first argument --- NEWS.md | 8 +++++++- base/deprecated.jl | 11 +++++++++++ base/distributed/cluster.jl | 6 +++++- base/distributed/clusterserialize.jl | 8 ++++++-- base/distributed/remotecall.jl | 4 ++-- base/distributed/workerpool.jl | 2 +- base/event.jl | 4 ++-- base/gcutils.jl | 6 +++--- base/gmp.jl | 2 +- base/iostream.jl | 2 +- base/libgit2/gitcredential.jl | 2 +- base/libgit2/types.jl | 10 +++++----- base/locks.jl | 2 +- base/mpfr.jl | 4 ++-- base/precompile.jl | 8 ++++---- base/process.jl | 2 +- base/regex.jl | 8 ++++---- base/repl/REPL.jl | 4 +++- base/socket.jl | 6 +++--- base/sparse/cholmod.jl | 6 +++--- base/sparse/umfpack.jl | 2 +- base/stream.jl | 6 +++--- base/weakkeydict.jl | 8 ++++---- stdlib/Base64/src/encode.jl | 2 +- stdlib/FileWatching/src/FileWatching.jl | 12 ++++++------ stdlib/FileWatching/test/runtests.jl | 2 +- stdlib/Mmap/src/Mmap.jl | 4 ++-- stdlib/SharedArrays/src/SharedArrays.jl | 2 +- test/ccall.jl | 4 ++-- test/channels.jl | 2 +- test/codegen.jl | 2 +- test/core.jl | 20 ++++++++++---------- test/dict.jl | 6 +++--- test/misc.jl | 2 +- 34 files changed, 103 insertions(+), 76 deletions(-) diff --git a/NEWS.md b/NEWS.md index d0af55c0f3a4a..6051347575ded 100644 --- a/NEWS.md +++ b/NEWS.md @@ -275,7 +275,13 @@ This section lists changes that do not have deprecation warnings. * The return type of `reinterpret` has changed to `ReinterpretArray`. `reinterpret` on sparse arrays has been discontinued. - * `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320]) + * `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320]). + + * `finalizer` now takes functions or pointers as its first argument, and the object being + finalized as its second (rather than the reverse). For the majority of use cases + deprecation warnings will be triggered. However, deprecation warnings will not trigger where + (1) the callable argument is not a subtype of `Function`; or (2) both arguments are + `Function`s or `Ptr{Void}`s ([#24605]). * The `kill` function now throws errors on user error (e.g. on permission errors), but returns successfully if the process had previously exited. diff --git a/base/deprecated.jl b/base/deprecated.jl index 3809223394d07..e28782d6f8758 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -2200,6 +2200,17 @@ end @deprecate chol!(x::Number, uplo) chol(x) false end + +# issue #16307 +@deprecate finalizer(o, f::Function) finalizer(f, o) +# This misses other callables but they are very rare in the wild +@deprecate finalizer(o, f::Ptr{Void}) finalizer(f, o) + +# Avoid ambiguity, can remove when deprecations are removed: +# This is almost certainly going to be a silent failure for code that is not updated. +finalizer(f::Ptr{Void}, o::Ptr{Void}) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o) +finalizer(f::Ptr{Void}, o::Function) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o) + # END 0.7 deprecations # BEGIN 1.0 deprecations diff --git a/base/distributed/cluster.jl b/base/distributed/cluster.jl index 34d367ecdbaa5..e05ca8e7f84e2 100644 --- a/base/distributed/cluster.jl +++ b/base/distributed/cluster.jl @@ -518,7 +518,11 @@ function create_worker(manager, wconfig) w = Worker(w.id, r_s, w_s, manager; config=wconfig) # install a finalizer to perform cleanup if necessary - finalizer(w, (w)->if myid() == 1 manage(w.manager, w.id, w.config, :finalize) end) + finalizer(w) do w + if myid() == 1 + manage(w.manager, w.id, w.config, :finalize) + end + end # set when the new worker has finshed connections with all other workers ntfy_oid = RRID() diff --git a/base/distributed/clusterserialize.jl b/base/distributed/clusterserialize.jl index 2a42f35a7f572..4a61f59710a2e 100644 --- a/base/distributed/clusterserialize.jl +++ b/base/distributed/clusterserialize.jl @@ -74,7 +74,9 @@ function serialize(s::ClusterSerializer, t::TypeName) serialize_typename(s, t) s.anonfunc_id = prev push!(s.tn_obj_sent, identifier) - finalizer(t, x->cleanup_tname_glbs(s, identifier)) + finalizer(t) do x + cleanup_tname_glbs(s, identifier) + end end # Send global refs if required. @@ -133,7 +135,9 @@ function serialize_global_from_main(s::ClusterSerializer, sym) elseif !haskey(s.glbs_sent, oid) # set up a finalizer the first time this object is sent try - finalizer(v, x->delete_global_tracker(s,x)) + finalizer(v) do x + delete_global_tracker(s,x) + end catch ex # Do not track objects that cannot be finalized. if isa(ex, ErrorException) diff --git a/base/distributed/remotecall.jl b/base/distributed/remotecall.jl index 1e87ba22b6698..b3503c4cc5339 100644 --- a/base/distributed/remotecall.jl +++ b/base/distributed/remotecall.jl @@ -52,13 +52,13 @@ function test_existing_ref(r::AbstractRemoteRef) end client_refs[r] = nothing - finalizer(r, finalize_ref) + finalizer(finalize_ref, r) return r end function finalize_ref(r::AbstractRemoteRef) if r.where > 0 # Handle the case of the finalizer having been called manually - islocked(client_refs) && return finalizer(r, finalize_ref) # delay finalizer for later, when it's not already locked + islocked(client_refs) && return finalizer(finalize_ref, r) # delay finalizer for later, when it's not already locked delete!(client_refs, r) if isa(r, RemoteChannel) send_del_client(r) diff --git a/base/distributed/workerpool.jl b/base/distributed/workerpool.jl index 7aedd63c844c4..cd034a7effd90 100644 --- a/base/distributed/workerpool.jl +++ b/base/distributed/workerpool.jl @@ -223,7 +223,7 @@ mutable struct CachingPool <: AbstractWorkerPool function CachingPool() wp = new(Channel{Int}(typemax(Int)), Set{Int}(), Dict{Int, Function}()) - finalizer(wp, clear!) + finalizer(clear!, wp) wp end end diff --git a/base/event.jl b/base/event.jl index f3b67726fea2e..5179e096714d4 100644 --- a/base/event.jl +++ b/base/event.jl @@ -303,7 +303,7 @@ mutable struct AsyncCondition function AsyncCondition() this = new(Libc.malloc(_sizeof_uv_async), Condition(), true) associate_julia_struct(this.handle, this) - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) err = ccall(:uv_async_init, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void}), eventloop(), this, uv_jl_asynccb::Ptr{Void}) if err != 0 @@ -372,7 +372,7 @@ mutable struct Timer end associate_julia_struct(this.handle, this) - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) ccall(:uv_update_time, Void, (Ptr{Void},), eventloop()) ccall(:uv_timer_start, Cint, (Ptr{Void}, Ptr{Void}, UInt64, UInt64), diff --git a/base/gcutils.jl b/base/gcutils.jl index e42cc9e6de303..b40108b08685a 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -5,13 +5,13 @@ ==(w, v::WeakRef) = isequal(w, v.value) """ - finalizer(x, f) + finalizer(f, x) Register a function `f(x)` to be called when there are no program-accessible references to `x`. The type of `x` must be a `mutable struct`, otherwise the behavior of this function is unpredictable. """ -function finalizer(@nospecialize(o), @nospecialize(f)) +function finalizer(@nospecialize(f), @nospecialize(o)) if isimmutable(o) error("objects of type ", typeof(o), " cannot be finalized") end @@ -19,7 +19,7 @@ function finalizer(@nospecialize(o), @nospecialize(f)) Core.getptls(), o, f) end -function finalizer(o::T, f::Ptr{Void}) where T +function finalizer(f::Ptr{Void}, o::T) where T @_inline_meta if isimmutable(T) error("objects of type ", T, " cannot be finalized") diff --git a/base/gmp.jl b/base/gmp.jl index 33eaa6e704c9a..5cb20f3189e77 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -55,7 +55,7 @@ mutable struct BigInt <: Signed function BigInt() b = new(zero(Cint), zero(Cint), C_NULL) MPZ.init!(b) - finalizer(b, cglobal((:__gmpz_clear, :libgmp))) + finalizer(cglobal((:__gmpz_clear, :libgmp)), b) return b end end diff --git a/base/iostream.jl b/base/iostream.jl index 33452f487fba3..24513f25e0f3d 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -18,7 +18,7 @@ function IOStream(name::AbstractString, finalize::Bool) buf = zeros(UInt8,sizeof_ios_t) x = IOStream(name, buf) if finalize - finalizer(x, close) + finalizer(close, x) end return x end diff --git a/base/libgit2/gitcredential.jl b/base/libgit2/gitcredential.jl index 99f6737fd639d..004ec0dd66b65 100644 --- a/base/libgit2/gitcredential.jl +++ b/base/libgit2/gitcredential.jl @@ -19,7 +19,7 @@ mutable struct GitCredential username::Nullable{<:AbstractString}, password::Nullable{<:AbstractString}) c = new(protocol, host, path, username, password, true) - finalizer(c, securezero!) + finalizer(securezero!, c) return c end end diff --git a/base/libgit2/types.jl b/base/libgit2/types.jl index 20a2efc643239..7c4e21b9a77d0 100644 --- a/base/libgit2/types.jl +++ b/base/libgit2/types.jl @@ -944,7 +944,7 @@ for (typ, owntyp, sup, cname) in [ obj = new(ptr) if fin Threads.atomic_add!(REFCOUNT, UInt(1)) - finalizer(obj, Base.close) + finalizer(Base.close, obj) end return obj end @@ -958,7 +958,7 @@ for (typ, owntyp, sup, cname) in [ obj = new(owner, ptr) if fin Threads.atomic_add!(REFCOUNT, UInt(1)) - finalizer(obj, Base.close) + finalizer(Base.close, obj) end return obj end @@ -1000,7 +1000,7 @@ mutable struct GitSignature <: AbstractGitObject function GitSignature(ptr::Ptr{SignatureStruct}) @assert ptr != C_NULL obj = new(ptr) - finalizer(obj, Base.close) + finalizer(Base.close, obj) return obj end end @@ -1144,7 +1144,7 @@ mutable struct UserPasswordCredentials <: AbstractCredentials pass::String function UserPasswordCredentials(user::AbstractString="", pass::AbstractString="") c = new(user, pass) - finalizer(c, securezero!) + finalizer(securezero!, c) return c end @@ -1182,7 +1182,7 @@ mutable struct SSHCredentials <: AbstractCredentials function SSHCredentials(user::AbstractString="", pass::AbstractString="", prvkey::AbstractString="", pubkey::AbstractString="") c = new(user, pass, prvkey, pubkey) - finalizer(c, securezero!) + finalizer(securezero!, c) return c end diff --git a/base/locks.jl b/base/locks.jl index e674d5d877191..6bf9c1274bc74 100644 --- a/base/locks.jl +++ b/base/locks.jl @@ -185,7 +185,7 @@ mutable struct Mutex <: AbstractLock function Mutex() m = new(zero(Int16), Libc.malloc(UV_MUTEX_SIZE)) ccall(:uv_mutex_init, Void, (Ptr{Void},), m.handle) - finalizer(m, _uv_hook_close) + finalizer(_uv_hook_close, m) return m end end diff --git a/base/mpfr.jl b/base/mpfr.jl index 743a814e1af88..3048657ee59d3 100644 --- a/base/mpfr.jl +++ b/base/mpfr.jl @@ -63,7 +63,7 @@ mutable struct BigFloat <: AbstractFloat prec = precision(BigFloat) z = new(zero(Clong), zero(Cint), zero(Clong), C_NULL) ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), z, prec) - finalizer(z, cglobal((:mpfr_clear, :libmpfr))) + finalizer(cglobal((:mpfr_clear, :libmpfr)), z) return z end @@ -969,7 +969,7 @@ function Base.deepcopy_internal(x::BigFloat, stackdict::ObjectIdDict) prec = precision(x) y = BigFloat(zero(Clong), zero(Cint), zero(Clong), C_NULL) ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), y, prec) - finalizer(y, cglobal((:mpfr_clear, :libmpfr))) + finalizer(cglobal((:mpfr_clear, :libmpfr)), y) ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), y, x, ROUNDING_MODE[]) stackdict[x] = y return y diff --git a/base/precompile.jl b/base/precompile.jl index 2ccd832138828..37ded112a894a 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -19,7 +19,7 @@ precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int precompile(Tuple{typeof(Base.empty!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}}) precompile(Tuple{typeof(Core.Inference.isbits), Base.Distributed.DefaultClusterManager}) precompile(Tuple{typeof(Base.Distributed.init_worker), String, Base.Distributed.DefaultClusterManager}) -precompile(Tuple{typeof(Base.finalizer), Base.TCPServer, typeof(Base.uvfinalize)}) +precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.TCPServer}) precompile(Tuple{Type{Base.TCPServer}, Ptr{Void}, Int64}) precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Int32}) precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.Libc.RawFD}) @@ -105,7 +105,7 @@ precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tu precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64}) precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64}) precompile(Tuple{typeof(Core.Inference.isbits), Base.DevNullStream}) -precompile(Tuple{typeof(Base.finalizer), Base.Process, typeof(Base.uvfinalize)}) +precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.Process}) precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Base.DevNullStream, Bool}}) precompile(Tuple{Type{Ref{Base.Cstring}}, Array{String, 1}}) precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{String, 1}}}) @@ -1552,7 +1552,7 @@ precompile(Tuple{typeof(Base.rehash!), Base.Dict{WeakRef, Void}, Int64}) precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{WeakRef, Void}, WeakRef}) precompile(Tuple{typeof(Base._setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef, Int64}) precompile(Tuple{typeof(Base.setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef}) -precompile(Tuple{typeof(Base.finalizer), Base.Distributed.RemoteChannel{Base.Channel{Any}}, typeof(Base.Distributed.finalize_ref)}) +precompile(Tuple{typeof(Base.finalizer), typeof(Base.Distributed.finalize_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}}) precompile(Tuple{Type{Base.Distributed.RemoteChannel{T} where T<:Base.AbstractChannel}, Int64}) precompile(Tuple{Type{Base.Channel{Int64}}, Int64}) @@ -1714,7 +1714,7 @@ precompile(Tuple{typeof(Base.Filesystem.mkdir), String, UInt16}) precompile(Tuple{typeof(Base.Filesystem.mkpath), String, UInt16}) precompile(Tuple{typeof(Base.Filesystem.samefile), String, String}) precompile(Tuple{typeof(Base.Filesystem.unlink), String}) -precompile(Tuple{typeof(Base.finalizer), Base.Distributed.Future, typeof(Base.Distributed.finalize_ref)}) +precompile(Tuple{typeof(Base.finalizer), typeof(Base.Distributed.finalize_ref), Base.Distributed.Future}) precompile(Tuple{typeof(Base.find_all_in_cache_path), Symbol}) precompile(Tuple{typeof(Base.find_package), String}) precompile(Tuple{typeof(Base.find_source_file), String}) diff --git a/base/process.jl b/base/process.jl index 84b921e607748..0d56aaee5b2f1 100644 --- a/base/process.jl +++ b/base/process.jl @@ -328,7 +328,7 @@ mutable struct Process <: AbstractPipe typemin(fieldtype(Process, :exitcode)), typemin(fieldtype(Process, :termsignal)), Condition(), Condition()) - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) return this end end diff --git a/base/regex.jl b/base/regex.jl index b82b7b75e3a05..344730007d7ec 100644 --- a/base/regex.jl +++ b/base/regex.jl @@ -29,10 +29,10 @@ mutable struct Regex end re = compile(new(pattern, compile_options, match_options, C_NULL, C_NULL, Csize_t[], C_NULL)) - finalizer(re, re->begin - re.regex == C_NULL || PCRE.free_re(re.regex) - re.match_data == C_NULL || PCRE.free_match_data(re.match_data) - end) + finalizer(re) do re + re.regex == C_NULL || PCRE.free_re(re.regex) + re.match_data == C_NULL || PCRE.free_match_data(re.match_data) + end re end end diff --git a/base/repl/REPL.jl b/base/repl/REPL.jl index 72203878b1696..d741824fec5d2 100644 --- a/base/repl/REPL.jl +++ b/base/repl/REPL.jl @@ -800,7 +800,9 @@ function setup_interface( try hist_path = find_hist_file() f = open(hist_path, true, true, true, false, false) - finalizer(replc, replc->close(f)) + finalizer(replc) do replc + close(f) + end hist_from_file(hp, f, hist_path) catch e print_response(repl, e, catch_backtrace(), true, Base.have_color) diff --git a/base/socket.jl b/base/socket.jl index 15330cd493556..541e1189bf844 100644 --- a/base/socket.jl +++ b/base/socket.jl @@ -278,7 +278,7 @@ mutable struct TCPSocket <: LibuvStream ReentrantLock(), DEFAULT_READ_BUFFER_SZ) associate_julia_struct(tcp.handle, tcp) - finalizer(tcp, uvfinalize) + finalizer(uvfinalize, tcp) return tcp end end @@ -308,7 +308,7 @@ mutable struct TCPServer <: LibuvServer Condition(), Condition()) associate_julia_struct(tcp.handle, tcp) - finalizer(tcp, uvfinalize) + finalizer(uvfinalize, tcp) return tcp end end @@ -370,7 +370,7 @@ mutable struct UDPSocket <: LibuvStream Condition(), Condition()) associate_julia_struct(udp.handle, udp) - finalizer(udp, uvfinalize) + finalizer(uvfinalize, udp) return udp end end diff --git a/base/sparse/cholmod.jl b/base/sparse/cholmod.jl index bf83ad849c79c..e4ea0ded03299 100644 --- a/base/sparse/cholmod.jl +++ b/base/sparse/cholmod.jl @@ -204,7 +204,7 @@ mutable struct Dense{T<:VTypes} <: DenseMatrix{T} "unknown reasons. Please submit a bug report.")) end A = new(p) - finalizer(A, free!) + finalizer(free!, A) return A end end @@ -256,7 +256,7 @@ mutable struct Sparse{Tv<:VTypes} <: AbstractSparseMatrix{Tv,SuiteSparse_long} "unknown reasons. Please submit a bug report.")) end A = new(p) - finalizer(A, free!) + finalizer(free!, A) return A end end @@ -340,7 +340,7 @@ mutable struct Factor{Tv} <: Factorization{Tv} end F = new(p) if register_finalizer - finalizer(F, free!) + finalizer(free!, F) end return F end diff --git a/base/sparse/umfpack.jl b/base/sparse/umfpack.jl index c71b6d2b65961..8355312cbbb66 100644 --- a/base/sparse/umfpack.jl +++ b/base/sparse/umfpack.jl @@ -143,7 +143,7 @@ function lufact(S::SparseMatrixCSC{<:UMFVTypes,<:UMFITypes}) zerobased ? copy(S.colptr) : decrement(S.colptr), zerobased ? copy(S.rowval) : decrement(S.rowval), copy(S.nzval)) - finalizer(res, umfpack_free_symbolic) + finalizer(umfpack_free_symbolic, res) umfpack_numeric!(res) end lufact(A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}) where {Ti<:UMFITypes} = diff --git a/base/stream.jl b/base/stream.jl index 15d050dc0ee60..4cf2d753f67ef 100644 --- a/base/stream.jl +++ b/base/stream.jl @@ -120,7 +120,7 @@ mutable struct PipeEndpoint <: LibuvStream ReentrantLock(), DEFAULT_READ_BUFFER_SZ) associate_julia_struct(handle, p) - finalizer(p, uvfinalize) + finalizer(uvfinalize, p) return p end end @@ -136,7 +136,7 @@ mutable struct PipeServer <: LibuvServer Condition(), Condition()) associate_julia_struct(p.handle, p) - finalizer(p, uvfinalize) + finalizer(uvfinalize, p) return p end end @@ -169,7 +169,7 @@ mutable struct TTY <: LibuvStream nothing, ReentrantLock(), DEFAULT_READ_BUFFER_SZ) associate_julia_struct(handle, tty) - finalizer(tty, uvfinalize) + finalizer(uvfinalize, tty) @static if Sys.iswindows() tty.ispty = ccall(:jl_ispty, Cint, (Ptr{Void},), handle) != 0 end diff --git a/base/weakkeydict.jl b/base/weakkeydict.jl index 1ff64f5b172b1..c4307271d7179 100644 --- a/base/weakkeydict.jl +++ b/base/weakkeydict.jl @@ -21,7 +21,7 @@ mutable struct WeakKeyDict{K,V} <: Associative{K,V} t = new(Dict{Any,V}(), Threads.RecursiveSpinLock(), identity) t.finalizer = function (k) # when a weak key is finalized, remove from dictionary if it is still there - islocked(t) && return finalizer(k, t.finalizer) + islocked(t) && return finalizer(t.finalizer, k) delete!(t, k) end return t @@ -89,7 +89,7 @@ trylock(f, wkh::WeakKeyDict) = trylock(f, wkh.lock) function setindex!(wkh::WeakKeyDict{K}, v, key) where K k = convert(K, key) - finalizer(k, wkh.finalizer) + finalizer(wkh.finalizer, k) lock(wkh) do wkh.ht[WeakRef(k)] = v end @@ -119,12 +119,12 @@ length(t::WeakKeyDict) = length(t.ht) function start(t::WeakKeyDict{K,V}) where V where K gc_token = Ref{Bool}(false) # no keys will be deleted via finalizers until this token is gc'd - finalizer(gc_token, function(r) + finalizer(gc_token) do r if r[] r[] = false unlock(t.lock) end - end) + end s = lock(t.lock) gc_token[] = true return (start(t.ht), gc_token) diff --git a/stdlib/Base64/src/encode.jl b/stdlib/Base64/src/encode.jl index 37dda446cd525..be44d5da07b92 100644 --- a/stdlib/Base64/src/encode.jl +++ b/stdlib/Base64/src/encode.jl @@ -39,7 +39,7 @@ struct Base64EncodePipe <: IO # The buffer size must be at least 3. buffer = Buffer(512) pipe = new(io, buffer) - finalizer(buffer, _ -> close(pipe)) + finalizer(_ -> close(pipe), buffer) return pipe end end diff --git a/stdlib/FileWatching/src/FileWatching.jl b/stdlib/FileWatching/src/FileWatching.jl index 5d2735dac8244..a8f91228f138b 100644 --- a/stdlib/FileWatching/src/FileWatching.jl +++ b/stdlib/FileWatching/src/FileWatching.jl @@ -75,7 +75,7 @@ mutable struct FileMonitor Libc.free(handle) throw(UVError("FileMonitor", err)) end - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) return this end end @@ -96,7 +96,7 @@ mutable struct PollingFileWatcher Libc.free(handle) throw(UVError("PollingFileWatcher", err)) end - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) return this end end @@ -144,7 +144,7 @@ mutable struct _FDWatcher Libc.free(handle) throw(UVError("FDWatcher", err)) end - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) FDWatchers[fdnum] = this return this end @@ -189,7 +189,7 @@ mutable struct _FDWatcher associate_julia_struct(handle, this) err = ccall(:uv_poll_init_socket, Int32, (Ptr{Void}, Ptr{Void}, Ptr{Void}), eventloop(), handle, fd.handle) - finalizer(this, uvfinalize) + finalizer(uvfinalize, this) if err != 0 Libc.free(handle) throw(UVError("FDWatcher", err)) @@ -206,13 +206,13 @@ mutable struct FDWatcher # WARNING: make sure `close` has been manually called on this watcher before closing / destroying `fd` function FDWatcher(fd::RawFD, readable::Bool, writable::Bool) this = new(_FDWatcher(fd, readable, writable), readable, writable) - finalizer(this, close) + finalizer(close, this) return this end @static if Sys.iswindows() function FDWatcher(fd::WindowsRawSocket, readable::Bool, writable::Bool) this = new(_FDWatcher(fd, readable, writable), readable, writable) - finalizer(this, close) + finalizer(close, this) return this end end diff --git a/stdlib/FileWatching/test/runtests.jl b/stdlib/FileWatching/test/runtests.jl index d6b0c3aeb7e0d..a39a8c9c74517 100644 --- a/stdlib/FileWatching/test/runtests.jl +++ b/stdlib/FileWatching/test/runtests.jl @@ -133,7 +133,7 @@ end # make sure repeating timers work @noinline function make_unrooted_timer(a) t = Timer(0.0, 0.1) - finalizer(t, t -> a[] += 1) + finalizer(t -> a[] += 1, t) wait(t) e = @elapsed for i = 1:5 wait(t) diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index 93c06ced89d1b..93eff5569c325 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -206,7 +206,7 @@ function mmap(io::IO, end # os-test # convert mmapped region to Julia Array at `ptr + (offset - offset_page)` since file was mapped at offset_page A = unsafe_wrap(Array, convert(Ptr{T}, UInt(ptr) + UInt(offset - offset_page)), dims) - finalizer(A, function(x) + finalizer(A) do x @static if Sys.isunix() systemerror("munmap", ccall(:munmap, Cint, (Ptr{Void}, Int), ptr, mmaplen) != 0) else @@ -214,7 +214,7 @@ function mmap(io::IO, status |= ccall(:CloseHandle, stdcall, Cint, (Ptr{Void},), handle)!=0 status || error("could not unmap view: $(Libc.FormatMessage())") end - end) + end return A end diff --git a/stdlib/SharedArrays/src/SharedArrays.jl b/stdlib/SharedArrays/src/SharedArrays.jl index 585a10a8049de..c5ac5ce01ae60 100644 --- a/stdlib/SharedArrays/src/SharedArrays.jl +++ b/stdlib/SharedArrays/src/SharedArrays.jl @@ -255,7 +255,7 @@ function initialize_shared_array(S, onlocalhost, init, pids) end end - finalizer(S, finalize_refs) + finalizer(finalize_refs, S) S end diff --git a/test/ccall.jl b/test/ccall.jl index 2f26ba5fae1e1..1b243b1dba6fd 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -881,13 +881,13 @@ end let A = [1] ccall((:set_c_int, libccalltest), Void, (Cint,), 1) @test ccall((:get_c_int, libccalltest), Cint, ()) == 1 - finalizer(A, cglobal((:finalizer_cptr, libccalltest), Void)) + finalizer(cglobal((:finalizer_cptr, libccalltest), Void), A) finalize(A) @test ccall((:get_c_int, libccalltest), Cint, ()) == -1 end # Pointer finalizer at exit (PR #19911) -let result = read(`$(Base.julia_cmd()) --startup-file=no -e "A = Ref{Cint}(42); finalizer(A, cglobal((:c_exit_finalizer, \"$libccalltest\"), Void))"`, String) +let result = read(`$(Base.julia_cmd()) --startup-file=no -e "A = Ref{Cint}(42); finalizer(cglobal((:c_exit_finalizer, \"$libccalltest\"), Void), A)"`, String) @test result == "c_exit_finalizer: 42, 0" end diff --git a/test/channels.jl b/test/channels.jl index d06592bb47e03..8a65ced7cd40a 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -226,7 +226,7 @@ end # test for yield/wait/event failures -@noinline garbage_finalizer(f) = finalizer("gar" * "bage", f) +@noinline garbage_finalizer(f) = finalizer(f, "gar" * "bage") let t, run = Ref(0) gc_enable(false) # test for finalizers trying to yield leading to failed attempts to context switch diff --git a/test/codegen.jl b/test/codegen.jl index d308ff81aa375..7664b90d29854 100644 --- a/test/codegen.jl +++ b/test/codegen.jl @@ -227,7 +227,7 @@ let was_gced = false function foo22770() b = Ref(2) - finalizer(b, x -> was_gced = true) + finalizer(x -> was_gced = true, b) y = make_tuple(b) x = y[1] a = Ref(1) diff --git a/test/core.jl b/test/core.jl index 154476f9c7509..c1fc395e2541d 100644 --- a/test/core.jl +++ b/test/core.jl @@ -896,7 +896,7 @@ end # finalizers let A = [1] local x = 0 - finalizer(A, a->(x+=1)) + finalizer(a->(x+=1), A) finalize(A) @test x == 1 A = 0 @@ -3593,7 +3593,7 @@ end let obj = Ref(1) finalized = 0 - finalizer(obj, (obj) -> (finalized = 1)) + finalizer((obj) -> (finalized = 1), obj) # obj should be marked for promotion after the second gc and be promoted # after the third GC # GC_CLEAN; age = 0 @@ -3623,10 +3623,10 @@ let obj1 = Ref(1) obj2 = Ref(1) finalized = 0 - finalizer(obj1, (obj) -> (finalized += 1)) - finalizer(obj1, (obj) -> (finalized += 1)) - finalizer(obj2, (obj) -> (finalized += 1; finalize(obj1))) - finalizer(obj2, (obj) -> (finalized += 1; finalize(obj1))) + finalizer((obj) -> (finalized += 1), obj1) + finalizer((obj) -> (finalized += 1), obj1) + finalizer((obj) -> (finalized += 1; finalize(obj1)), obj2) + finalizer((obj) -> (finalized += 1; finalize(obj1)), obj2) finalize(obj2) @test finalized == 4 end @@ -3963,10 +3963,10 @@ end # doesn't keep the object alive. @noinline function create_dead_object13995(finalized) obj = Ref(1) - finalizer(obj, (x)->(finalized[1] = true)) - finalizer(obj, (x)->(finalized[2] = true)) - finalizer(obj, (x)->(finalized[3] = true)) - finalizer(obj, (x)->(finalized[4] = true)) + finalizer((x)->(finalized[1] = true), obj) + finalizer((x)->(finalized[2] = true), obj) + finalizer((x)->(finalized[3] = true), obj) + finalizer((x)->(finalized[4] = true), obj) nothing end # disable GC to make sure no collection/promotion happens diff --git a/test/dict.jl b/test/dict.jl index 8c0f22e383592..77df74d3e0625 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -613,9 +613,9 @@ Dict(1 => rand(2,3), 'c' => "asdf") # just make sure this does not trigger a dep local x = 0 local y = 0 local z = 0 - finalizer(A, a->(x+=1)) - finalizer(B, b->(y+=1)) - finalizer(C, c->(z+=1)) + finalizer(a->(x+=1), A) + finalizer(b->(y+=1), B) + finalizer(c->(z+=1), C) # construction wkd = WeakKeyDict() diff --git a/test/misc.jl b/test/misc.jl index 75d5a2012c971..33f4dcca2c671 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -269,7 +269,7 @@ end @noinline function f6597(c) t = @schedule nothing - finalizer(t, t -> c[] += 1) + finalizer(t -> c[] += 1, t) wait(t) @test c[] == 0 wait(t)