diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2021-06-14 14:52:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-14 14:52:49 +0200 |
commit | 1e1959f6fac6dd0e499532772c8143285cdd81de (patch) | |
tree | a321b9351d1d860b4e6026896cc45966cae96c8d /runtime/ops/http.rs | |
parent | 5814315b708d154ebb2c29810c16e5af7e726741 (diff) |
fix: hang in Deno.serveHttp() (#10923)
Waiting on next request in Deno.serveHttp() API hanged
when responses were using ReadableStream. This was caused
by op_http_request_next op that was never woken after
response was fully written. This commit adds waker field to
DenoService which is called after response is finished.
Diffstat (limited to 'runtime/ops/http.rs')
-rw-r--r-- | runtime/ops/http.rs | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/runtime/ops/http.rs b/runtime/ops/http.rs index fedcb404f..11e83f6c7 100644 --- a/runtime/ops/http.rs +++ b/runtime/ops/http.rs @@ -66,6 +66,7 @@ struct ServiceInner { #[derive(Clone, Default)] struct Service { inner: Rc<RefCell<Option<ServiceInner>>>, + waker: Rc<deno_core::futures::task::AtomicWaker>, } impl HyperService<Request<Body>> for Service { @@ -160,15 +161,16 @@ async fn op_http_request_next( let cancel = RcRef::map(conn_resource.clone(), |r| &r.cancel); poll_fn(|cx| { + conn_resource.deno_service.waker.register(cx.waker()); let connection_closed = match conn_resource.poll(cx) { Poll::Pending => false, Poll::Ready(Ok(())) => { - // close ConnResource - state + // try to close ConnResource, but don't unwrap as it might + // already be closed + let _ = state .borrow_mut() .resource_table - .take::<ConnResource>(conn_rid) - .unwrap(); + .take::<ConnResource>(conn_rid); true } Poll::Ready(Err(e)) => { @@ -188,7 +190,6 @@ async fn op_http_request_next( } } }; - if let Some(request_resource) = conn_resource.deno_service.inner.borrow_mut().take() { @@ -409,6 +410,9 @@ async fn op_http_response( }) .await?; + if maybe_response_body_rid.is_none() { + conn_resource.deno_service.waker.wake(); + } Ok(maybe_response_body_rid) } @@ -430,11 +434,13 @@ async fn op_http_response_close( .ok_or_else(bad_resource_id)?; drop(resource); - poll_fn(|cx| match conn_resource.poll(cx) { + let r = poll_fn(|cx| match conn_resource.poll(cx) { Poll::Ready(x) => Poll::Ready(x), Poll::Pending => Poll::Ready(Ok(())), }) - .await + .await; + conn_resource.deno_service.waker.wake(); + r } async fn op_http_request_read( |