diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 59e2fdd428..750167ca78 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -159,6 +159,9 @@ pub enum BlockReason { Epoll, /// Blocked on eventfd. Eventfd, + /// Blocked on unnamed_socket. + UnnamedSocket, + } /// The state of a thread. diff --git a/src/shims/unix/unnamed_socket.rs b/src/shims/unix/unnamed_socket.rs index 232f4500db..7791027c20 100644 --- a/src/shims/unix/unnamed_socket.rs +++ b/src/shims/unix/unnamed_socket.rs @@ -160,14 +160,30 @@ impl FileDescription for AnonSocket { // Since there is no ErrorKind for EAGAIN, WouldBlock is used. return ecx.set_last_error_and_return(ErrorKind::WouldBlock, dest); } else { + // TODO: move this to helper // Blocking socketpair with writer and empty buffer. - // FIXME: blocking is currently not supported - throw_unsup_format!("socketpair/pipe/pipe2 read: blocking isn't supported yet"); + let peer_fd = self.peer_fd().upgrade().unwrap(); + bytes = bytes.clone(); + ecx.block_thread( + BlockReason::UnnamedSocket, + None, + callback!( + @capture<'tcx> { + self_ref: FileDescriptionRef, + peer_fd: Option, + bytes: [u8], + ptr: Pointer, + dest: MPlaceTy<'tcx>, + } + @unblock = |this| { + // TODO: We might need to decide what to do if peer_fd is closed when read is blocked. + anonsocket_read(self_ref, peer_fd, &bytes, ptr, dest, ecx) + } + ), + ); } } } - // TODO: We might need to decide what to do if peer_fd is closed when read is blocked. - anonsocket_read(self, self.peer_fd().upgrade(), &mut bytes, ptr, dest, ecx) } fn write<'tcx>( @@ -249,13 +265,14 @@ fn anonsocket_write<'tcx>( /// Read from AnonSocket and return the number of bytes read. fn anonsocket_read<'tcx>( - anonsocket: &AnonSocket, + self_ref: FileDescriptionRef, peer_fd: Option, - bytes: &mut [u8], + bytes: &[u8], ptr: Pointer, dest: &MPlaceTy<'tcx>, ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx> { + let anonsocket = self_ref.downcast::().unwrap(); let Some(readbuf) = &anonsocket.readbuf else { // FIXME: This should return EBADF, but there's no nice way to do that as there's no // corresponding ErrorKind variant.