Skip to content

Commit

Permalink
fix(ext/flash): reregister socket on partial read on Windows (#16076)
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy authored Sep 28, 2022
1 parent fcb20ab commit e2828ad
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 15 deletions.
29 changes: 29 additions & 0 deletions cli/tests/unit/flash_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2205,6 +2205,35 @@ Deno.test(
},
);

// https://github.com/denoland/deno/issues/15549
Deno.test(
{ permissions: { net: true } },
async function testIssue15549() {
const ac = new AbortController();
const promise = deferred();
let count = 0;
const server = Deno.serve(() => {
count++;
return new Response(`hello world ${count}`);
}, {
async onListen() {
const res1 = await fetch("http://localhost:9000/");
assertEquals(await res1.text(), "hello world 1");

const res2 = await fetch("http://localhost:9000/");
assertEquals(await res2.text(), "hello world 2");

promise.resolve();
ac.abort();
},
signal: ac.signal,
});

await promise;
await server;
},
);

function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
const tp = new TextProtoReader(r);
Expand Down
56 changes: 41 additions & 15 deletions ext/flash/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -987,22 +987,48 @@ fn run_server(
// sockets.remove(&token);
continue 'events;
}
Ok(read) => match req.parse(&buffer[..offset + read]) {
Ok(httparse::Status::Complete(n)) => {
body_offset = n;
body_len = offset + read;
socket.parse_done = ParseStatus::None;
break;
}
Ok(httparse::Status::Partial) => {
socket.parse_done = ParseStatus::Ongoing(offset + read);
continue;
}
Err(_) => {
let _ = socket.write(b"HTTP/1.1 400 Bad Request\r\n\r\n");
continue 'events;
Ok(read) => {
match req.parse(&buffer[..offset + read]) {
Ok(httparse::Status::Complete(n)) => {
body_offset = n;
body_len = offset + read;
socket.parse_done = ParseStatus::None;
// On Windows, We must keep calling socket.read() until it fails with WouldBlock.
//
// Mio tries to emulate edge triggered events on Windows.
// AFAICT it only rearms the event on WouldBlock, but it doesn't when a partial read happens.
// https://github.com/denoland/deno/issues/15549
#[cfg(target_os = "windows")]
match &mut socket.inner {
InnerStream::Tcp(ref mut socket) => {
poll
.registry()
.reregister(socket, token, Interest::READABLE)
.unwrap();
}
InnerStream::Tls(ref mut socket) => {
poll
.registry()
.reregister(
&mut socket.sock,
token,
Interest::READABLE,
)
.unwrap();
}
};
break;
}
Ok(httparse::Status::Partial) => {
socket.parse_done = ParseStatus::Ongoing(offset + read);
continue;
}
Err(_) => {
let _ = socket.write(b"HTTP/1.1 400 Bad Request\r\n\r\n");
continue 'events;
}
}
},
}
Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
break 'events
}
Expand Down

0 comments on commit e2828ad

Please sign in to comment.