Skip to content

Commit cabd0d0

Browse files
authored
Postpone StickyMessages cleanup to outside of finalizer (#7)
IO cannot be done from within the finalizer. Also add a test for empty!() which wasn't tested.
1 parent f18fed9 commit cabd0d0

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/StickyMessages.jl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,19 @@ function StickyMessages(io::IO; ansi_codes=io isa Base.TTY &&
2626
!Sys.iswindows())
2727
sticky = StickyMessages(io, ansi_codes, Vector{Pair{Any,String}}())
2828
# Ensure we clean up the terminal
29-
finalizer(empty!, sticky)
29+
finalizer(sticky) do sticky
30+
# See also empty!()
31+
if !sticky.ansi_codes
32+
return
33+
end
34+
prev_nlines = _countlines(sticky.messages)
35+
if prev_nlines > 0
36+
# Clean up sticky lines. Hack: must be async to do the IO outside
37+
# of finalizer. Proper fix would be an uninstall event triggered by
38+
# with_logger.
39+
@async showsticky(sticky.io, prev_nlines, [])
40+
end
41+
end
3042
sticky
3143
end
3244

test/StickyMessages.jl

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,35 @@ end
3939
push!(stickies, :a=>"αβγ\n")
4040
@test String(take!(buf)) == #scroll #csr #pos #msg #pos
4141
"\e[20;1H\n\e[1;19r\e[20;1Hαβγ\e[19;1H"
42+
43+
push!(stickies, :b=>"msg\n")
44+
take!(buf)
45+
46+
# Remove all two messages
47+
empty!(stickies)
48+
@test String(take!(buf)) == #clear #csr #pos
49+
"\e[19;1H\e[J\e[1;20r\e[18;1H"
50+
end
51+
52+
@noinline func_barrier(f) = f()
53+
54+
@testset "Sticky messages with ANSI codes" begin
55+
buf = IOBuffer()
56+
dsize = (20, 80) # Intentionally different from default of 25 rows
57+
func_barrier() do
58+
# Hide stickies variable behind a function barrier to make sure(er)
59+
# that it can be GC'd.
60+
stickies = StickyMessages(IOContext(buf, :displaysize=>dsize), ansi_codes=true)
61+
push!(stickies, :a=>"a-msg\n")
62+
push!(stickies, :b=>"b-msg\n")
63+
take!(buf)
64+
nothing
65+
end
66+
# Hack to force StickyMessages finalizer
67+
GC.gc(true) # trigger finalizer
68+
for i=1:1000
69+
yield() # allow async cleanup
70+
end
71+
@test String(take!(buf)) == #clear #csr #pos
72+
"\e[19;1H\e[J\e[1;20r\e[18;1H"
4273
end

0 commit comments

Comments
 (0)