diff --git a/src/shims/unix/unnamed_socket.rs b/src/shims/unix/unnamed_socket.rs index 22c744e706..bd990aa533 100644 --- a/src/shims/unix/unnamed_socket.rs +++ b/src/shims/unix/unnamed_socket.rs @@ -100,11 +100,15 @@ impl FileDescription for AnonSocket { // corresponding ErrorKind variant. throw_unsup_format!("reading from the write end of a pipe"); }; + let peer_fd = self.peer_fd().clone(); + let dest = dest.clone(); + let weak_self_ref = self_ref.downgrade(); + // TODO: move this to helper if readbuf.borrow().buf.is_empty() { if self.peer_fd().upgrade().is_none() { // Socketpair with no peer and empty buffer. // 0 bytes successfully read indicates end-of-file. - return ecx.return_read_success(ptr, &[], 0, dest); + return ecx.return_read_success(ptr, &[], 0, &dest); } else { if self.is_nonblock { // Non-blocking socketpair with writer and empty buffer. @@ -112,13 +116,9 @@ impl FileDescription for AnonSocket { // EAGAIN or EWOULDBLOCK can be returned for socket, // POSIX.1-2001 allows either error to be returned for this case. // Since there is no ErrorKind for EAGAIN, WouldBlock is used. - return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); + return ecx.set_last_error_and_return(ErrorKind::WouldBlock, &dest); } else { - // TODO: move this to helper // Blocking socketpair with writer and empty buffer. - let peer_fd = self.peer_fd().clone(); - let dest = dest.clone(); - let weak_self_ref = self_ref.downgrade(); ecx.block_thread( BlockReason::UnnamedSocket, None, @@ -138,6 +138,8 @@ impl FileDescription for AnonSocket { ); } } + } else { + return anonsocket_read(weak_self_ref, peer_fd, len, ptr, dest, ecx); } interp_ok(()) } @@ -171,14 +173,15 @@ impl FileDescription for AnonSocket { }; let available_space = MAX_SOCKETPAIR_BUFFER_CAPACITY.strict_sub(writebuf.borrow().buf.len()); + let peer_fd = peer_fd.downgrade(); + let dest = dest.clone(); + // TODO: move this to helper if available_space == 0 { if self.is_nonblock { // Non-blocking socketpair with a full buffer. - return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); + return ecx.set_last_error_and_return(ErrorKind::WouldBlock, &dest); } else { // Blocking socketpair with a full buffer. - let peer_fd = peer_fd.downgrade(); - let dest = dest.clone(); ecx.block_thread( BlockReason::UnnamedSocket, None, @@ -197,6 +200,8 @@ impl FileDescription for AnonSocket { ), ); } + } else { + return anonsocket_write(available_space, peer_fd, ptr, len, dest, ecx); } interp_ok(()) } diff --git a/tests/fail-dep/libc/socketpair_read_blocking.rs b/tests/fail-dep/libc/socketpair_read_blocking.rs index ffa4e36f0f..b3b30cb3fe 100644 --- a/tests/fail-dep/libc/socketpair_read_blocking.rs +++ b/tests/fail-dep/libc/socketpair_read_blocking.rs @@ -8,5 +8,5 @@ fn main() { let _ = unsafe { libc::socketpair(libc::AF_UNIX, libc::SOCK_STREAM, 0, fds.as_mut_ptr()) }; // The read below will be blocked because the buffer is empty. let mut buf: [u8; 3] = [0; 3]; - let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; //~ERROR: blocking isn't supported + let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; //~ERROR: deadlock } diff --git a/tests/fail-dep/libc/socketpair_read_blocking.stderr b/tests/fail-dep/libc/socketpair_read_blocking.stderr index 16892614c6..caf23da115 100644 --- a/tests/fail-dep/libc/socketpair_read_blocking.stderr +++ b/tests/fail-dep/libc/socketpair_read_blocking.stderr @@ -1,10 +1,9 @@ -error: unsupported operation: socketpair/pipe/pipe2 read: blocking isn't supported yet +error: deadlock: the evaluated program deadlocked --> tests/fail-dep/libc/socketpair_read_blocking.rs:LL:CC | LL | let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair/pipe/pipe2 read: blocking isn't supported yet + | ^ the evaluated program deadlocked | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: = note: inside `main` at tests/fail-dep/libc/socketpair_read_blocking.rs:LL:CC diff --git a/tests/fail-dep/libc/socketpair_write_blocking.rs b/tests/fail-dep/libc/socketpair_write_blocking.rs index e83197dfc0..cd499bbd15 100644 --- a/tests/fail-dep/libc/socketpair_write_blocking.rs +++ b/tests/fail-dep/libc/socketpair_write_blocking.rs @@ -10,7 +10,7 @@ fn main() { let _ = unsafe { libc::write(fds[0], arr1.as_ptr() as *const libc::c_void, 212992) }; let data = "abc".as_bytes().as_ptr(); // The write below will be blocked as the buffer is full. - let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; //~ERROR: blocking isn't supported + let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; //~ERROR: deadlock let mut buf: [u8; 3] = [0; 3]; let _res = unsafe { libc::read(fds[1], buf.as_mut_ptr().cast(), buf.len() as libc::size_t) }; } diff --git a/tests/fail-dep/libc/socketpair_write_blocking.stderr b/tests/fail-dep/libc/socketpair_write_blocking.stderr index a2fcf87578..2dc420d5f1 100644 --- a/tests/fail-dep/libc/socketpair_write_blocking.stderr +++ b/tests/fail-dep/libc/socketpair_write_blocking.stderr @@ -1,10 +1,9 @@ -error: unsupported operation: socketpair/pipe/pipe2 write: blocking isn't supported yet +error: deadlock: the evaluated program deadlocked --> tests/fail-dep/libc/socketpair_write_blocking.rs:LL:CC | LL | let _ = unsafe { libc::write(fds[0], data as *const libc::c_void, 3) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ socketpair/pipe/pipe2 write: blocking isn't supported yet + | ^ the evaluated program deadlocked | - = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support = note: BACKTRACE: = note: inside `main` at tests/fail-dep/libc/socketpair_write_blocking.rs:LL:CC