From d818a272c0641e6b853b9712eaaf689fb7dc9cc7 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Tue, 19 Mar 2024 12:38:57 -0400 Subject: [PATCH] add try finally to close --- src/stream.jl | 13 ++++++++----- test/codecdoubleframe.jl | 33 +++++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/stream.jl b/src/stream.jl index d4d8625e..e4056ffc 100644 --- a/src/stream.jl +++ b/src/stream.jl @@ -184,11 +184,14 @@ end function Base.close(stream::TranscodingStream) mode = stream.state.mode - if mode != :panic - changemode!(stream, :close) - end - if !stream.state.stop_on_end - close(stream.stream) + try + if mode != :panic + changemode!(stream, :close) + end + finally + if !stream.state.stop_on_end + close(stream.stream) + end end return nothing end diff --git a/test/codecdoubleframe.jl b/test/codecdoubleframe.jl index 4b5e4e53..4b8efb74 100644 --- a/test/codecdoubleframe.jl +++ b/test/codecdoubleframe.jl @@ -26,20 +26,20 @@ function TranscodingStreams.process( codec :: DoubleFrameEncoder, input :: TranscodingStreams.Memory, output :: TranscodingStreams.Memory, - error :: TranscodingStreams.Error, + error_ref :: TranscodingStreams.Error, ) if input.size == 0 codec.got_stop_msg[] = true end if output.size < 2 - error[] = ErrorException("requires a minimum of 2 bytes of output space") + error_ref[] = ErrorException("requires a minimum of 2 bytes of output space") return 0, 0, :error elseif codec.stopped[] - error[] = ErrorException("cannot process after stopped") + error_ref[] = ErrorException("cannot process after stopped") return 0, 0, :error elseif codec.got_stop_msg[] && input.size != 0 - error[] = ErrorException("cannot accept more input after getting stop message") + error_ref[] = ErrorException("cannot accept more input after getting stop message") return 0, 0, :error elseif !codec.opened[] output[1] = UInt8('[') @@ -95,7 +95,7 @@ function TranscodingStreams.process( codec :: DoubleFrameDecoder, input :: TranscodingStreams.Memory, output :: TranscodingStreams.Memory, - error :: TranscodingStreams.Error, + error_ref :: TranscodingStreams.Error, ) Δin::Int = 0 Δout::Int = 0 @@ -167,7 +167,7 @@ function TranscodingStreams.process( catch e codec.state[]=7 e isa ErrorException || rethrow() - error[] = e + error_ref[] = e return Δin, Δout, :error end end @@ -243,6 +243,27 @@ DoubleFrameDecoderStream(stream::IO; kwargs...) = TranscodingStream(DoubleFrameD @test String(take!(sink)) == "[ ][ aabbcc ][ ddee ]" end + @testset "Issue #160 Safely close stream after failure" begin + sink = IOBuffer() + stream = TranscodingStream(DoubleFrameDecoder(), sink) + write(stream, "abc") + @test_throws ErrorException("expected [") close(stream) + @test !isopen(stream) + @test !isopen(sink) + + @testset "nested decoders" begin + sink = IOBuffer() + stream = TranscodingStream(DoubleFrameDecoder(), sink) + stream2 = TranscodingStream(DoubleFrameDecoder(), stream) + write(stream2, "abc") + # "expected byte" error with caused by "expected [" + @test_throws ErrorException("expected byte") close(stream2) + @test !isopen(stream2) + @test !isopen(stream) + @test !isopen(sink) + end + end + test_roundtrip_read(DoubleFrameEncoderStream, DoubleFrameDecoderStream) test_roundtrip_write(DoubleFrameEncoderStream, DoubleFrameDecoderStream) test_roundtrip_lines(DoubleFrameEncoderStream, DoubleFrameDecoderStream)