Skip to content

File descriptor abstraction #11

@vbe0201

Description

@vbe0201

With our asynchronous socket(), we have the very first operation working with file descriptors on board. This also immediately brings us to yet another design challenge for an abstraction in our system:

class Resource:
    def __init__(self, handle: int, direct: bool):
        self._handle = handle
        self._direct = direct

    async def __aenter__(self) -> typing.Self:
        return self

    async def __aexit__(self, *exc: typing.Any):
        await self.close()

    async def close(self):
        handle, self._handle = self._handle, -1
        await cancel_all_fd_ops(handle, self.direct)
        await self.close(handle, self.direct)

You'll notice that handle sure enough is our file descriptor and the direct flag to distinguish regular file descriptors and io_uring direct descriptors.

Direct descriptors?

io_uring has a cool feature where you preallocate a sparse table of descriptors and then you can allocate direct descriptors to it which act synonymous to regular file descriptors. The difference is that manipulating them is more efficient because they avoid the fget/fput overhead associated with refcounting in the kernel.

We want to be able to use both in boros so some distinction is necessary.

Closing resources

When closing a resource, it is very important that we first cancel all ongoing operations and invalidate the object. This will also prevent consumers from scheduling more operations on the same file after cancellation.

This is very important to prevent race conditions where a descriptor gets freed, reassigned to another resource, and then previously scheduled operations manipulate the new resource.

And mimicking existing APIs commonly found in Python, we offer both an explicit close method and context manager ergonomics.

Naming

Should we actually name the close method close? Since this will be the first sample of public API in boros, we want to continue with a uniform style in the future.

aclose is also a somewhat popular alternative.

Optimization

We can link the cancellation and the close operation together into a single chained operation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions