async def write(self, dest: Pointer, data: bytes) -> None: if dest.size() != len(data): raise Exception("mismatched pointer size", dest.size(), "and data size", len(data)) while True: conn = await self.conn_queue.request(Get()) assert conn is not None try: recv_fut = Future.start(conn.infallible_recv(to_span(dest))) await self.write_to_fd(data) return await recv_fut.get() except SyscallSendError as exc: await self.conn_queue.request(Broken(conn))
async def send_all(self, to_write: Pointer, flags: MSG) -> None: """Write all of this pointer to the fd, retrying on partial writes until complete. See `AsyncFileDescriptor.write_all` and `AsyncFileDescriptor.send`. """ while to_write.size() > 0: written, to_write = await self.send(to_write, flags)
async def write_all(self, to_write: Pointer) -> None: """Write all of this pointer to the fd, retrying on partial writes until complete. You might want to not use this, if you want to react to a partial write in some special way. """ while to_write.size() > 0: written, to_write = await self.write(to_write)
async def write_all(self, to_write: Pointer) -> None: """Write all of this pointer to the fd, retrying on partial writes until complete. You might want to not use this, if you want to react to a partial write in some special way. For example, `rsyscall.memory.socket_transport.SocketMemoryTransport` starts a `recv` immediately after a partial write, before retrying the write, for increased parallelism. """ while to_write.size() > 0: written, to_write = await self.write(to_write)
async def read(self, src: Pointer) -> bytes: while True: conn = await self.conn_queue.request(Get()) assert conn is not None try: # these two operations have to be working on the same conn, or things will be deeply wrong. # thankfully, they're both issued and sequenced with conn_queue.request right next to each other, # so they can't get different conns. # note also that we can't just call conn.read_from_fd directly, # because conn.infallible_send goes through Task.sysif which is the PersistentSyscallConnection, # so the two operations would be sequenced differently from each other read_fut = Future.start(self.read_from_fd(src.size())) await conn.infallible_send(src) return await read_fut.get() except BrokenPipeError: # infallible_send might actually fail with EPIPE due to being called on the old broken conn, # but going through the new working conn. # it also might fail due to the connection just plain dying. # in either case, the connection is now broken. # also, in either case, we know that if read_fut.get() would have failed with a SyscallSendError, # then infallible_send would fail with BrokenPipeError. # so we only need to catch BrokenPipeError. await self.conn_queue.request(Broken(conn))
async def read(self, src: Pointer) -> bytes: src = to_span(src) dest = await self.local.ram.malloc(bytes, src.size()) async def write() -> None: rest = src while rest.size() > 0: written, rest = await self.remote.write(rest) async with trio.open_nursery() as nursery: nursery.start_soon(write) read: t.Optional[Pointer[bytes]] = None rest = dest while rest.size() > 0: more_read, rest = await self.local.read(rest) if read is None: read = more_read else: read = read.merge(more_read) if read is None: return b'' else: return await read.read()
async def read(self, src: Pointer) -> bytes: self.logger.debug("reading from %s", src) read_fut = Future.start(self.read_from_fd(src.size())) await self.infallible_send(src) return await read_fut.get()
async def write(self, dest: Pointer, data: bytes) -> None: if dest.size() != len(data): raise Exception("mismatched pointer size", dest.size(), "and data size", len(data)) self.logger.debug("writing to %s, num bytes: %s", dest, len(data)) reset(self.infallible_recv(to_span(dest))) await self.write_to_fd(data)
async def write_all(self, to_write: Pointer) -> None: "Write all of this pointer to the fd, retrying on partial writes until complete." while to_write.size() > 0: written, to_write = await self.handle.write(to_write)
async def read(self, src: Pointer) -> bytes: if src.mapping.task.address_space != self.local_task.address_space: raise Exception("trying to read from pointer", src, "not in local address space") buf = ffi.buffer(ffi.cast('void*', int(src.near)), src.size()) return bytes(buf)