diff --git a/base/locks-mt.jl b/base/locks-mt.jl index 1efafe2822065..6a3b68016cb81 100644 --- a/base/locks-mt.jl +++ b/base/locks-mt.jl @@ -87,6 +87,7 @@ function trylock(l::SpinLock) end function unlock(l::SpinLock) + _get(l) == 0 && error("unlock count must match lock count") _set!(l, 0) GC.enable_finalizers(true) ccall(:jl_cpu_wake, Cvoid, ()) diff --git a/src/gc.c b/src/gc.c index cf4c00f710633..c991e38296577 100644 --- a/src/gc.c +++ b/src/gc.c @@ -411,7 +411,12 @@ JL_DLLEXPORT void jl_gc_enable_finalizers(jl_ptls_t ptls, int on) } JL_CATCH { jl_printf((JL_STREAM*)STDERR_FILENO, "WARNING: GC finalizers already enabled on this thread. Possibly unpaired within a try block?\n"); - jlbacktrace(); // written to STDERR_FILENO + // Only print the backtrace once, to avoid spamming the logs + static int backtrace_printed = 0; + if (backtrace_printed == 0) { + backtrace_printed = 1; + jlbacktrace(); // written to STDERR_FILENO + } } return; } diff --git a/test/misc.jl b/test/misc.jl index dd8ad47bc9129..33faa4b09eee8 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -126,7 +126,7 @@ end # Debugging tool: return the current state of the enable_finalizers counter. enable_finalizers_count() = ccall(:jl_gc_get_enable_finalizers, Int32, (Ptr{Cvoid},), C_NULL) -let l = ReentrantLock() +for l in (Threads.SpinLock(), ReentrantLock()) @test enable_finalizers_count() == 0 @test lock(enable_finalizers_count, l) == 1 @test enable_finalizers_count() == 0 diff --git a/test/threads_exec.jl b/test/threads_exec.jl index 691fca2fb2afa..c21ef45389f96 100644 --- a/test/threads_exec.jl +++ b/test/threads_exec.jl @@ -112,10 +112,10 @@ test_threaded_atomic_minmax(UInt16(27000),UInt16(37000)) function threaded_add_locked(::Type{LockT}, x, n) where LockT critical = LockT() @threads for i = 1:n - @test lock(critical) === nothing + lock(critical) @test islocked(critical) x = x + 1 - @test unlock(critical) === nothing + unlock(critical) end @test !islocked(critical) nentered = 0 @@ -124,7 +124,7 @@ function threaded_add_locked(::Type{LockT}, x, n) where LockT if trylock(critical) @test islocked(critical) nentered += 1 - @test unlock(critical) === nothing + unlock(critical) else atomic_add!(nfailed, 1) end @@ -142,21 +142,21 @@ end let critical = ReentrantLock() @test !islocked(critical) @test_throws ErrorException("unlock count must match lock count") unlock(critical) - @test lock(critical) === nothing + lock(critical) @test islocked(critical) - @test lock(critical) === nothing - @test trylock(critical) == true + lock(critical) + t = trylock(critical); @test t @test islocked(critical) - @test unlock(critical) === nothing + unlock(critical) @test islocked(critical) - @test unlock(critical) === nothing + unlock(critical) @test islocked(critical) - @test unlock(critical) === nothing + unlock(critical) @test !islocked(critical) @test_throws ErrorException("unlock count must match lock count") unlock(critical) - @test trylock(critical) == true + t = trylock(critical); @test t @test islocked(critical) - @test unlock(critical) === nothing + unlock(critical) @test !islocked(critical) @test_throws ErrorException("unlock count must match lock count") unlock(critical) @test !islocked(critical) @@ -167,10 +167,10 @@ end function threaded_gc_locked(::Type{LockT}) where LockT critical = LockT() @threads for i = 1:20 - @test lock(critical) === nothing + lock(critical) @test islocked(critical) GC.gc(false) - @test unlock(critical) === nothing + unlock(critical) end @test !islocked(critical) end