Handle ErrorKind::Interrupted when doing stream IO
When doing IO with the underlying stream object, we should handle the special case of ErrorKind::Interrupted, otherwise the connection will be closed incorrectly. Quotation from Rust doc: An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read operation should be retried if there is nothing else to do. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
This commit is contained in:
committed by
Andreea Florescu
parent
0d87a94c8e
commit
c9ffb90aeb
@@ -1 +1 @@
|
|||||||
{"coverage_score": 93.2, "exclude_path": "", "crate_features": ""}
|
{"coverage_score": 92.8, "exclude_path": "", "crate_features": ""}
|
||||||
|
|||||||
@@ -117,18 +117,16 @@ impl<T: Read + Write> HttpConnection<T> {
|
|||||||
// Reads a maximum of `BUFFER_SIZE` bytes from the stream into `buffer`.
|
// Reads a maximum of `BUFFER_SIZE` bytes from the stream into `buffer`.
|
||||||
// The return value represents the end index of what we have just appended.
|
// The return value represents the end index of what we have just appended.
|
||||||
fn read_bytes(&mut self) -> Result<usize, ConnectionError> {
|
fn read_bytes(&mut self) -> Result<usize, ConnectionError> {
|
||||||
// Append new bytes to what we already have in the buffer.
|
loop {
|
||||||
let bytes_read = self
|
// Append new bytes to what we already have in the buffer.
|
||||||
.stream
|
match self.stream.read(&mut self.buffer[self.read_cursor..]) {
|
||||||
.read(&mut self.buffer[self.read_cursor..])
|
// If the read returned 0 then the client has closed the connection.
|
||||||
.map_err(ConnectionError::StreamError)?;
|
Ok(0) => return Err(ConnectionError::ConnectionClosed),
|
||||||
|
Ok(bytes_read) => return Ok(bytes_read + self.read_cursor),
|
||||||
// If the read returned 0 then the client has closed the connection.
|
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
|
||||||
if bytes_read == 0 {
|
Err(e) => return Err(ConnectionError::StreamError(e)),
|
||||||
return Err(ConnectionError::ConnectionClosed);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(bytes_read + self.read_cursor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parses bytes in `buffer` for a valid request line.
|
// Parses bytes in `buffer` for a valid request line.
|
||||||
@@ -324,9 +322,7 @@ impl<T: Read + Write> HttpConnection<T> {
|
|||||||
if let Some(response_buffer_vec) = self.response_buffer.as_mut() {
|
if let Some(response_buffer_vec) = self.response_buffer.as_mut() {
|
||||||
let bytes_to_be_written = response_buffer_vec.len();
|
let bytes_to_be_written = response_buffer_vec.len();
|
||||||
match self.stream.write(response_buffer_vec.as_slice()) {
|
match self.stream.write(response_buffer_vec.as_slice()) {
|
||||||
Ok(0) | Err(_) => {
|
Ok(0) => connection_closed = true,
|
||||||
connection_closed = true;
|
|
||||||
}
|
|
||||||
Ok(bytes_written) => {
|
Ok(bytes_written) => {
|
||||||
if bytes_written != bytes_to_be_written {
|
if bytes_written != bytes_to_be_written {
|
||||||
response_buffer_vec.drain(..bytes_written);
|
response_buffer_vec.drain(..bytes_written);
|
||||||
@@ -334,6 +330,8 @@ impl<T: Read + Write> HttpConnection<T> {
|
|||||||
response_fully_written = true;
|
response_fully_written = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {}
|
||||||
|
Err(_) => connection_closed = true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user