Skip to content

Commit 555e595

Browse files
fix nio read/write iovec bugs causing deadlock and infinite loop
Agent-Logs-Url: https://github.com/acl-dev/open-coroutine/sessions/3ee10e36-26e4-49a6-88c3-bc465b166e2f Co-authored-by: loongs-zhang <38336731+loongs-zhang@users.noreply.github.com>
1 parent 601ea78 commit 555e595

2 files changed

Lines changed: 14 additions & 16 deletions

File tree

core/src/syscall/unix/mod.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ macro_rules! impl_nio_read_iovec {
566566
let mut received = 0usize;
567567
let mut r = -1;
568568
let mut index = 0;
569-
for iovec in &vec {
570-
let mut offset = received.saturating_sub(length);
569+
'outer: for iovec in &vec {
570+
let offset = received.saturating_sub(length);
571571
length += iovec.iov_len;
572572
if received > length {
573573
index += 1;
@@ -603,11 +603,9 @@ macro_rules! impl_nio_read_iovec {
603603
} else if r != -1 {
604604
$crate::syscall::reset_errno();
605605
received += libc::size_t::try_from(r).expect("r overflow");
606-
if received >= length {
607-
r = received.try_into().expect("received overflow");
608-
break;
609-
}
610-
offset = received.saturating_sub(length);
606+
r = received.try_into().expect("received overflow");
607+
// readv returns as soon as any data is received
608+
break 'outer;
611609
}
612610
let error_kind = std::io::Error::last_os_error().kind();
613611
if error_kind == std::io::ErrorKind::WouldBlock {

core/src/syscall/windows/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ macro_rules! impl_nio_read_iovec {
533533
let mut received = 0usize;
534534
let mut r = windows_sys::Win32::Networking::WinSock::SOCKET_ERROR;
535535
let mut index = 0;
536-
for iovec in &vec {
536+
'outer: for iovec in &vec {
537537
let mut offset = received.saturating_sub(length);
538538
length += iovec.len as usize;
539539
if received > length {
@@ -563,13 +563,12 @@ macro_rules! impl_nio_read_iovec {
563563
);
564564
if r != windows_sys::Win32::Networking::WinSock::SOCKET_ERROR {
565565
$crate::syscall::reset_errno();
566-
received += usize::try_from(r).expect("overflow");
567-
if received >= length {
568-
r = 0;
569-
unsafe{ $recvd.write(received.try_into().expect("overflow")) };
570-
break;
571-
}
572-
offset = received.saturating_sub(length);
566+
// WSARecv returns 0 on success; actual byte count is in *$recvd
567+
received += unsafe { *$recvd } as usize;
568+
r = 0;
569+
unsafe{ $recvd.write(received.try_into().expect("overflow")) };
570+
// WSARecv returns as soon as any data is received
571+
break 'outer;
573572
}
574573
let error_kind = std::io::Error::last_os_error().kind();
575574
if error_kind == std::io::ErrorKind::WouldBlock {
@@ -803,7 +802,8 @@ macro_rules! impl_nio_write_iovec {
803802
);
804803
if r != windows_sys::Win32::Networking::WinSock::SOCKET_ERROR {
805804
$crate::syscall::reset_errno();
806-
sent += usize::try_from(r).expect("overflow");
805+
// WSASend returns 0 on success; actual byte count is in *$sent
806+
sent += unsafe { *$sent } as usize;
807807
if sent >= length {
808808
r = 0;
809809
unsafe{ $sent.write(sent.try_into().expect("overflow")) };

0 commit comments

Comments
 (0)