Пример #1
0
 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))
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
 def to_handle(cffi_ptr) -> Pointer[NativeFunction]:
     pointer_int = int(ffi.cast('ssize_t', cffi_ptr))
     # TODO we're just making up a memory mapping that this pointer is inside;
     # we should figure out the actual mapping, and the size for that matter.
     mapping = MemoryMapping(task,
                             near.MemoryMapping(pointer_int, 0, 1),
                             far.File())
     return Pointer(mapping, NullGateway(), NativeFunctionSerializer(),
                    StaticAllocation())
Пример #5
0
    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)
Пример #6
0
    async def malloc_serializer(self, serializer: Serializer[T],
                                size: int) -> Pointer[T]:
        """Allocate a typed space in memory using an explicitly-specified Serializer.

        This is useful only in relatively niche situations.

        """
        mapping, allocation = await self.allocator.malloc(size, alignment=1)
        try:
            return Pointer(mapping, self.transport, serializer, allocation)
        except:
            allocation.free()
            raise
Пример #7
0
 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))
Пример #8
0
    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()
Пример #9
0
 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()
Пример #10
0
 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)
Пример #11
0
 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)
Пример #12
0
 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)
Пример #13
0
def to_span(ptr: Pointer) -> Pointer:
    "Wraps the pointer's allocation in SpanAllocation so it can be split freely"
    return Pointer(ptr.mapping, ptr.serializer,
                   SpanAllocation(ptr.allocation, 0, ptr.allocation.size()),
                   ptr.typ)
Пример #14
0
def merge_adjacent_pointers(ptrs: t.List[Pointer]) -> Pointer:
    "Merges these pointers together by wrapping the allocation in a MergedAllocation"
    return Pointer(ptrs[0].mapping, ptrs[0].transport, ptrs[0].serializer,
                   MergedAllocation([ptr.allocation for ptr in ptrs]))