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

Refactor JVM unixsockets #3165

Merged
merged 1 commit into from
Mar 20, 2023

Conversation

armanbilge
Copy link
Member

I'm working on supporting HTTP/2 over unix sockets in Ember and was experiencing a lot of strange issues e.g. non-deterministic behavior, reads returning empty chunks, hanging.

The bad news was that I was unable to replicate these issues as unit tests 🤔 this is where I started from, focused on just the empty read issue, before I gave up and went for the refactor.

The good news is that I published a snapshot and (spoiler alert) was surprised to discover that this refactor somehow fixed everything 😅 wasn't really expecting that.

This refactor mostly addresses these three issues:

  1. Not switching the sockets to non-blocking mode. I suspect that this was what was causing the empty reads bug in Ember. Non-blocking mode is only useful if you are using a selector to poll for events on the socket. Otherwise, you have no way of knowing when there are bytes available on the socket, so you may get empty reads / no-op writes, and be forced to degrade to a busy-loop, which is much worse than doing a blocking read (or write) to begin with.

    Note that when the Cats Effect polling system stuff lands, we will be able to register the JDK unix sockets with the polling system and thus have non-blocking reads/writes, so that's something to look forward to.

  2. Carefully wrapping a socket in a resource as soon as it is opened, so that it is guaranteed to be closed in all instances. Attempting to tack on other side-effects as part of the acquire phase (e.g., binding or connecting) may lead to a resource leak if those actions fail, because then the socket is never returned, which means it can never be closed, etc.

  3. Properly suspending side-effects e.g. interactions with ByteBuffers, blocking, etc.

serverChannel.bind(UnixDomainSocketAddress.of(address.path))
(F.blocking(serverChannel.accept()), F.blocking(serverChannel.close()))
}
protected def openChannel(address: UnixSocketAddress) =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add return types?

@mpilquist mpilquist merged commit 9738c9c into typelevel:main Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants