fix dealloc issues

This commit is contained in:
Martin Algesten
2018-10-23 20:18:24 +01:00
parent df7b5ca839
commit 2c9e62ad8c
3 changed files with 35 additions and 23 deletions

View File

@@ -89,10 +89,10 @@ impl<R: Read + Sized> PoolReturnRead<R> {
return; return;
} }
let state = &mut unit.agent.lock().unwrap(); let state = &mut unit.agent.lock().unwrap();
if let Some(agent) = state.as_mut() { // bring back stream here to either go into pool or dealloc
unsafe { let stream = unsafe { *Box::from_raw(self.stream) };
let stream = *Box::from_raw(self.stream);
self.stream = ::std::ptr::null_mut(); self.stream = ::std::ptr::null_mut();
if let Some(agent) = state.as_mut() {
if !stream.is_poolable() { if !stream.is_poolable() {
// just let it deallocate // just let it deallocate
return; return;
@@ -101,7 +101,6 @@ impl<R: Read + Sized> PoolReturnRead<R> {
let key = PoolKey::new(&unit.url); let key = PoolKey::new(&unit.url);
agent.pool().recycle.insert(key, stream); agent.pool().recycle.insert(key, stream);
} }
};
} }
} }
@@ -124,3 +123,9 @@ impl<R: Read + Sized> Read for PoolReturnRead<R> {
Ok(amount) Ok(amount)
} }
} }
impl<R: Read + Sized> Drop for PoolReturnRead<R> {
fn drop(&mut self) {
self.return_connection();
}
}

View File

@@ -276,7 +276,7 @@ impl Response {
let stream = Box::new(self.stream.expect("No reader in response?!")); let stream = Box::new(self.stream.expect("No reader in response?!"));
let stream_ptr = Box::into_raw(stream); let stream_ptr = Box::into_raw(stream);
let yolo = YoloRead { stream: stream_ptr }; let mut yolo = YoloRead { stream: stream_ptr, dealloc: false };
let unit = self.unit; let unit = self.unit;
match (use_chunked, limit_bytes) { match (use_chunked, limit_bytes) {
@@ -290,7 +290,10 @@ impl Response {
stream_ptr, stream_ptr,
LimitedRead::new(yolo, len), LimitedRead::new(yolo, len),
)), )),
(false, None) => Box::new(yolo), (false, None) => {
yolo.dealloc = true; // dealloc when read drops.
Box::new(yolo)
},
} }
} }
@@ -521,6 +524,7 @@ fn read_next_line<R: Read>(reader: &mut R) -> IoResult<AsciiString> {
/// *Internal API* /// *Internal API*
struct YoloRead { struct YoloRead {
stream: *mut Stream, stream: *mut Stream,
dealloc: bool, // whether we are to dealloc stream on drop
} }
impl Read for YoloRead { impl Read for YoloRead {
@@ -531,6 +535,9 @@ impl Read for YoloRead {
} }
let amount = (*self.stream).read(buf)?; let amount = (*self.stream).read(buf)?;
if amount == 0 { if amount == 0 {
if self.dealloc {
let _stream = Box::from_raw(self.stream);
}
self.stream = ::std::ptr::null_mut(); self.stream = ::std::ptr::null_mut();
} }
Ok(amount) Ok(amount)
@@ -538,6 +545,16 @@ impl Read for YoloRead {
} }
} }
impl Drop for YoloRead {
fn drop(&mut self) {
if self.dealloc && !self.stream.is_null() {
unsafe {
let _stream = Box::from_raw(self.stream);
}
}
}
}
/// Limits a YoloRead to a content size (as set by a "Content-Length" header). /// Limits a YoloRead to a content size (as set by a "Content-Length" header).
/// ///
/// *Internal API* /// *Internal API*

View File

@@ -18,16 +18,6 @@ pub enum Stream {
Test(Box<dyn Read + Send>, Vec<u8>), Test(Box<dyn Read + Send>, Vec<u8>),
} }
impl Drop for Stream {
fn drop(&mut self) {
match self {
#[cfg(feature = "tls")]
Stream::Https(s) => { s.shutdown().ok(); },
_ => (),
}
}
}
impl ::std::fmt::Debug for Stream { impl ::std::fmt::Debug for Stream {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::result::Result<(), ::std::fmt::Error> {
write!( write!(