Skip to content

Commit

Permalink
Avoid all 'unhandled exceptions' from h2spec run
Browse files Browse the repository at this point in the history
They're mostly related to broken IO (EPIPE, ECONNRESET, EOF) or
pending fibers (e.g. waiting to write data to `stream.data`).
  • Loading branch information
ysbaddaden committed Oct 25, 2017
1 parent 781666c commit 1640610
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/connection.cr
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ module HTTP2

when Frame::Type::GOAWAY
_, last_stream_id = read_stream_id
error_code = Error::Code.from_value(io.read_bytes(UInt32, IO::ByteFormat::BigEndian))
error_code = Error::Code.new(io.read_bytes(UInt32, IO::ByteFormat::BigEndian))
io.read_fully(buf = Slice(UInt8).new(frame.size - 8))
error_message = String.new(buf)

Expand Down Expand Up @@ -332,7 +332,7 @@ module HTTP2
# synchronisation could end up corrupted if another HEADERS frame for
# another stream was sent in between.
def send(frame : Frame | Array(Frame))
@channel.send(frame)
@channel.send(frame) unless @channel.closed?
end

def write_settings
Expand Down
6 changes: 3 additions & 3 deletions src/hpack/huffman.cr
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module HTTP2
eos_padding = false
end

raise Exception.new("node is nil!") unless node
raise Error.new("node is nil!") unless node

if value = node.value
io.write_byte(value)
Expand All @@ -88,11 +88,11 @@ module HTTP2
end

# RFC 7541, section 5.2
raise Exception.new("huffman string padding is larger than 7-bits") unless byte_has_value
raise Error.new("huffman string padding is larger than 7-bits") unless byte_has_value
end

# RFC 7541, section 5.2
raise Exception.new("huffman string padding must use MSB of EOS symbol") unless eos_padding
raise Error.new("huffman string padding must use MSB of EOS symbol") unless eos_padding

io.to_s
end
Expand Down
23 changes: 13 additions & 10 deletions src/server/request_processor.cr
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,22 @@ class HTTP::Server::RequestProcessor
# didn't read it all, for the next request
request.body.try(&.close)
end
ensure
io.close if must_close
end

rescue ex : Errno
# FIXME: calling with curl results in EPIPE (certainly related to
# SSL::Error below)
raise ex unless ex.errno == Errno::EPIPE
rescue ex : IO::EOFError | IO::Error
# silence

rescue ex : OpenSSL::SSL::Error
# FIXME: calling with curl results in "SSL_read: ZERO_RETURN" exception
# (certainly related to EPIPE above)
raise ex unless ex.message.try(&.includes?("ZERO_RETURN"))
rescue ex : Errno
raise ex unless {Errno::EPIPE, Errno::ECONNRESET}.includes?(ex.errno)

ensure
io.close if must_close
rescue ex : OpenSSL::SSL::Error
# NOTE: curl calls may result in "SSL_read: ZERO_RETURN" exceptions
# NOTE: unexpectedly closed connections may result in OpenSSL hitting EOF early
unless ex.message.try(&.includes?("ZERO_RETURN")) ||
ex.message.try(&.includes?("Unexpected EOF"))
raise ex
end
end

Expand Down
2 changes: 1 addition & 1 deletion src/stream.cr
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ module HTTP2

protected def send_window_update_frame(increment)
unless MINIMUM_WINDOW_SIZE <= increment <= MAXIMUM_WINDOW_SIZE
raise Exception.new("invalid WINDOW_UPDATE increment: #{increment}")
raise Error.protocol_error("invalid WINDOW_UPDATE increment: #{increment}")
end
io = IO::Memory.new
io.write_bytes(increment.to_u32 & 0x7fffffff_u32, IO::ByteFormat::BigEndian)
Expand Down

0 comments on commit 1640610

Please sign in to comment.