Ref count stream state and release when final (#73)

Previously, stream state was never released so that long-lived connections
leaked memory.

Now, stream states are reference-counted and freed from the stream slab
when complete.  Locally reset streams are retained so that received frames
may be ignored.
This commit is contained in:
Carl Lerche
2017-09-10 16:01:19 -07:00
committed by Oliver Gould
parent daa54b9512
commit 5c0efcf8c4
15 changed files with 542 additions and 190 deletions

View File

@@ -149,6 +149,58 @@ fn send_headers_recv_data_single_frame() {
h2.wait().unwrap();
}
#[test]
fn closed_streams_are_released() {
let _ = ::env_logger::init();
let (io, srv) = mock::new();
let h2 = Client::handshake(io).unwrap()
.and_then(|mut h2| {
let request = Request::get("https://example.com/")
.body(()).unwrap();
// Send request
let stream = h2.request(request, true).unwrap();
h2.drive(stream)
})
.and_then(|(h2, response)| {
assert_eq!(response.status(), StatusCode::NO_CONTENT);
// There are no active streams
assert_eq!(0, h2.num_active_streams());
// The response contains a handle for the body. This keeps the
// stream wired.
assert_eq!(1, h2.num_wired_streams());
drop(response);
// The stream state is now free
assert_eq!(0, h2.num_wired_streams());
Ok(())
})
;
let srv = srv.assert_client_handshake().unwrap()
.recv_settings()
.recv_frame(
frames::headers(1)
.request("GET", "https://example.com/")
.eos()
)
.send_frame(
frames::headers(1)
.response(204)
.eos()
)
.close()
;
let _ = h2.join(srv)
.wait().unwrap();
}
/*
#[test]
fn send_data_after_headers_eos() {

View File

@@ -71,23 +71,35 @@ impl<T, U> Future for Drive<T, U>
type Error = ();
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
match self.future.poll() {
Ok(Async::Ready(val)) => {
// Get the driver
let driver = self.driver.take().unwrap();
let mut looped = false;
return Ok((driver, val).into())
loop {
match self.future.poll() {
Ok(Async::Ready(val)) => {
// Get the driver
let driver = self.driver.take().unwrap();
return Ok((driver, val).into())
}
Ok(_) => {}
Err(e) => panic!("unexpected error; {:?}", e),
}
Ok(_) => {}
Err(e) => panic!("unexpected error; {:?}", e),
}
match self.driver.as_mut().unwrap().poll() {
Ok(Async::Ready(_)) => panic!("driver resolved before future"),
Ok(Async::NotReady) => {}
Err(e) => panic!("unexpected error; {:?}", e),
}
match self.driver.as_mut().unwrap().poll() {
Ok(Async::Ready(_)) => {
if looped {
// Try polling the future one last time
panic!("driver resolved before future")
} else {
looped = true;
continue;
}
}
Ok(Async::NotReady) => {}
Err(e) => panic!("unexpected error; {:?}", e),
}
Ok(Async::NotReady)
return Ok(Async::NotReady);
}
}
}