Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Return wait_readable or something equivalent #15374

Open
yxhuvud opened this issue Jan 25, 2025 · 3 comments
Open

Return wait_readable or something equivalent #15374

yxhuvud opened this issue Jan 25, 2025 · 3 comments
Assignees

Comments

@yxhuvud
Copy link
Contributor

yxhuvud commented Jan 25, 2025

Feature Request

Waiting on a file descriptor to become readable is an increasingly common way on linux systems to tie together C-libraries that are async in one way or another. Examples are libwayland-client and libpipewire, but there are others as well. It is just better in every way than having to spawn a separate thread to run those (these libraries also provide fully blocking functions that interact with the fds). This used to integrate super well with the crystal event loop by making use of wait_readable : example: https://github.com/yxhuvud/wayland_client/blob/main/src/display.cr#L50.

However, in crystal 1.15 wait_readable (and the less useful wait_writable) was removed as part of the other event loop work. It would be nice to have them back, or to have some other way to achieve the same end result, as it allows clean integration with these libraries even in single threaded mode. I'd be totally fine in having them back documented as unstable and subject to change while waiting for a more long-term solution.

These methods are not implementable on Windows (especially not wait_writable - wait_readable might be by resorting to private functions). That is a problem, but the use case is to do bindings with libraries that are not multi-platform anyhow, so it shouldn't be a blocker as this is functionality that really can't be implemented by thirdparty libraries in an easy way without resorting to monkey-patching stdlib.

@yxhuvud
Copy link
Contributor Author

yxhuvud commented Jan 25, 2025

Removal seems to have broken spider-gazelle/ssh2.cr#22 too, so I'm not alone in having this issue.

@straight-shoota
Copy link
Member

Just FTR because it's not 100% clear from the OP: wait_readable and wait_writable have always been internal APIs and were not indended for direct use from user code.

I do understand the use case though and agree that we should offer a solution, ideall with a public, supported API ;)

Perhaps a simple replacement would be to make the respective methods in Crystal::EventLoop::Polling visible?

For a proper API, I'm wondering if we could use a zero-size read (or write) operation.
Apparently this mechanism works with IOCP as well and that's how this could be implemented on Windows (at least for sockets; not sure about other file descriptors).

@GrantBirki
Copy link

we should offer a solution, ideally with a public, supported API

+1 to this. Having public methods for wait_readable and wait_writable would be nice

@ysbaddaden ysbaddaden self-assigned this Jan 27, 2025
straight-shoota pushed a commit that referenced this issue Feb 6, 2025
These methods in the `Crystal::EventLoop` interfaces wait on file descriptor or socket readiness without performing an actual read or write operation, which can be delegated to an external library.

This provides a semi-public interface to work around #15374:

```crystal
file_descriptor = IO::FileDescriptor.new(LibC.some_fd, blocking: false)

event_loop = Crystal::EventLoop.current
event_loop.wait_readable(file_descriptor)
LibC.do_something(fd)
```

This is implemented for the polling event loops (epoll, kqueue) as well as libevent since these were straightforward.

Windows is left unimplemented. It might be implemented with `WSAPoll` running in a thread or `ProcessSocketNotifications` to associate sockets to a completion port. See [Winsock socket state notifications](https://learn.microsoft.com/en-us/windows/win32/winsock/winsock-socket-state-notifications) for more details.


Related to [RFC #7](https://github.com/crystal-lang/rfcs/blob/main/text/0007-event_loop-refactor.md) and [RFC #9](https://github.com/crystal-lang/rfcs/blob/main/text/0009-lifetime-event_loop.md).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants