Skip to content

Commit 31a0440

Browse files
mxindendjc
authored andcommitted
fix(udp): retry on ErrorKind::Interrupted
On Linux and Android, `quinn-udp` will retry a send on `ErrorKind::Interrupted`: https://github.com/quinn-rs/quinn/blob/e318cc4a80436fd9fa19c02886d682c49efca185/quinn-udp/src/unix.rs#L305-L312 Do the same on all other unix platforms.
1 parent 53e13f2 commit 31a0440

File tree

1 file changed

+35
-30
lines changed

1 file changed

+35
-30
lines changed

quinn-udp/src/unix.rs

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -383,25 +383,27 @@ fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io:
383383
hdrs[i].msg_datalen = chunk.len();
384384
cnt += 1;
385385
}
386-
let n = unsafe { sendmsg_x(io.as_raw_fd(), hdrs.as_ptr(), cnt as u32, 0) };
387-
if n >= 0 {
388-
return Ok(());
389-
}
390-
let e = io::Error::last_os_error();
391-
match e.kind() {
392-
io::ErrorKind::Interrupted => {
393-
// Retry the transmission
394-
}
395-
io::ErrorKind::WouldBlock => return Err(e),
396-
_ => {
397-
// - EMSGSIZE is expected for MTU probes. Future work might be able to avoid
398-
// these by automatically clamping the MTUD upper bound to the interface MTU.
399-
if e.raw_os_error() != Some(libc::EMSGSIZE) {
400-
return Err(e);
386+
loop {
387+
let n = unsafe { sendmsg_x(io.as_raw_fd(), hdrs.as_ptr(), cnt as u32, 0) };
388+
if n == -1 {
389+
let e = io::Error::last_os_error();
390+
match e.kind() {
391+
io::ErrorKind::Interrupted => {
392+
// Retry the transmission
393+
continue;
394+
}
395+
io::ErrorKind::WouldBlock => return Err(e),
396+
_ => {
397+
// - EMSGSIZE is expected for MTU probes. Future work might be able to avoid
398+
// these by automatically clamping the MTUD upper bound to the interface MTU.
399+
if e.raw_os_error() != Some(libc::EMSGSIZE) {
400+
return Err(e);
401+
}
402+
}
401403
}
402404
}
405+
return Ok(());
403406
}
404-
Ok(())
405407
}
406408

407409
#[cfg(any(target_os = "openbsd", target_os = "netbsd", apple_slow))]
@@ -419,24 +421,27 @@ fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io:
419421
cfg!(apple) || cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd"),
420422
state.sendmsg_einval(),
421423
);
422-
let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) };
423-
if n == -1 {
424-
let e = io::Error::last_os_error();
425-
match e.kind() {
426-
io::ErrorKind::Interrupted => {
427-
// Retry the transmission
428-
}
429-
io::ErrorKind::WouldBlock => return Err(e),
430-
_ => {
431-
// - EMSGSIZE is expected for MTU probes. Future work might be able to avoid
432-
// these by automatically clamping the MTUD upper bound to the interface MTU.
433-
if e.raw_os_error() != Some(libc::EMSGSIZE) {
434-
return Err(e);
424+
loop {
425+
let n = unsafe { libc::sendmsg(io.as_raw_fd(), &hdr, 0) };
426+
if n == -1 {
427+
let e = io::Error::last_os_error();
428+
match e.kind() {
429+
io::ErrorKind::Interrupted => {
430+
// Retry the transmission
431+
continue;
432+
}
433+
io::ErrorKind::WouldBlock => return Err(e),
434+
_ => {
435+
// - EMSGSIZE is expected for MTU probes. Future work might be able to avoid
436+
// these by automatically clamping the MTUD upper bound to the interface MTU.
437+
if e.raw_os_error() != Some(libc::EMSGSIZE) {
438+
return Err(e);
439+
}
435440
}
436441
}
437442
}
443+
return Ok(());
438444
}
439-
Ok(())
440445
}
441446

442447
#[cfg(not(any(apple, target_os = "openbsd", target_os = "netbsd", solarish)))]

0 commit comments

Comments
 (0)