Skip to content

Commit e613aef

Browse files
committed
Start socket timeout after the sock snapshot
A 1ms CGI handler timeout was expiring during lock/scheduling delay before poll, so macOS closed the connection with RST under load. sendall still reuses one deadline for the write. Assisted-by: Grok:4.6
1 parent aaf1809 commit e613aef

1 file changed

Lines changed: 14 additions & 8 deletions

File tree

‎crates/stdlib/src/socket.rs‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -970,23 +970,30 @@ mod _socket {
970970
where
971971
F: FnMut() -> io::Result<R>,
972972
{
973-
let deadline = self.get_timeout().ok().map(Deadline::new);
974-
self.sock_op_timeout_err(vm, wait_kind, deadline, f)
973+
let timeout = self.get_timeout().ok();
974+
let mut deadline = None;
975+
self.sock_op_timeout_err(vm, wait_kind, &mut deadline, timeout, f)
975976
}
976977

977978
fn sock_op_timeout_err<F, R>(
978979
&self,
979980
vm: &VirtualMachine,
980981
wait_kind: SockWaitKind,
981-
deadline: Option<Deadline>,
982+
deadline: &mut Option<Deadline>,
983+
timeout: Option<Duration>,
982984
mut f: F,
983985
) -> Result<R, IoOrPyException>
984986
where
985987
F: FnMut() -> io::Result<R>,
986988
{
987989
loop {
988-
if deadline.is_some() || matches!(wait_kind, SockWaitKind::Connect) {
990+
if timeout.is_some() || matches!(wait_kind, SockWaitKind::Connect) {
989991
let sock = self.sock_snapshot()?;
992+
// Start the clock after the snapshot so lock/scheduling
993+
// delay is not subtracted from a short timeout before poll.
994+
if deadline.is_none() {
995+
*deadline = timeout.map(Deadline::new);
996+
}
990997
sock_wait_deadline(&sock, wait_kind, deadline.as_ref(), vm)?;
991998
}
992999

@@ -999,7 +1006,7 @@ mod _socket {
9991006
Err(e) => break e,
10001007
}
10011008
};
1002-
if deadline.is_some() && err.kind() == io::ErrorKind::WouldBlock {
1009+
if timeout.is_some() && err.kind() == io::ErrorKind::WouldBlock {
10031010
continue;
10041011
}
10051012
return Err(err.into());
@@ -1717,15 +1724,14 @@ mod _socket {
17171724
let flags = flags.unwrap_or(0);
17181725

17191726
let timeout = self.get_timeout().ok();
1720-
1721-
let deadline = timeout.map(Deadline::new);
1727+
let mut deadline = None;
17221728

17231729
let buf = bytes.borrow_buf_unlocked(vm)?;
17241730
let buf = &*buf;
17251731
let mut buf_offset = 0;
17261732
// now we have like 3 layers of interrupt loop :)
17271733
while buf_offset < buf.len() {
1728-
self.sock_op_timeout_err(vm, SockWaitKind::Write, deadline, || {
1734+
self.sock_op_timeout_err(vm, SockWaitKind::Write, &mut deadline, timeout, || {
17291735
let subbuf = &buf[buf_offset..];
17301736
buf_offset += self.sock_snapshot()?.send_with_flags(subbuf, flags)?;
17311737
Ok(())

0 commit comments

Comments
 (0)