Skip to content

Do not invoke accept() on an already-established connection #105

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ppentchev
Copy link

@ppentchev ppentchev commented Oct 27, 2024

Hi,

First of all, thanks a lot for writing and maintaining the Rust reference implementation of varlink!

Here's a proposed fix for #73; the Listener::new() method already records the fact that this listener is actually a connection that has already been established via socket activation, and lets the Listener::accept() method honor that flag.

I have written a trivial varlink server - my varlink-hello GitLab project - to demonstrate the need for this change. Without it, with the stock varlink 11.0.1 crate, the varlink-hello program fails, since Listener::accept() attempts to invoke the accept() method of the "Unix listener" which is actually an already-connected socket.

Now, there are three things I don't completely like about this patch:

  • I'm not overly fond of the use of unsafe { ... } in Listener::accept(). A cleaner way to do that would be to add two new values to the Listener enum, e.g. TCPAccepted and UNIXAccepted, and make Listener::new() create a TcpListener or a UnixListener directly, in its own unsafe { ... } blocks. This might cause a bit of code churn; let me know if I should do it.
  • I currently have no way of testing the Windows implementation; I'd be very grateful if somebody could try to build the varlink-hello program under Windows and see if a) it fails with the currently-released varlink crate, and b) this change fixes it.
  • I am not entirely sure how to write tests for this change. An obvious way would be to copy the test_listen() function in varlink/src/tests.rs, create a socketpair, and go for it, but the problem is that to really test it, the LISTEN_FDS, LISTEN_FDNAMES, and LISTEN_PID environment variables need to be set, which might influence other tests run either at the same time or later. I'd be grateful for any ideas on how to approach this; writing a new binary crate that will only be used for testing almost seems like a viable approach, even though Cargo currently does not support test-only binary crates.

Thanks in advance for your time, and keep up the great work!

G'luck,
Peter

Listener::new() already records the fact that this listener is actually
a connection that has already been established via socket activation.
Let Listener::accept() honor that flag.

Fixes varlink#73.
@ppentchev
Copy link
Author

JFTR, I edited the initial comment to add the third thing I'm not completely sure about.

@@ -151,6 +151,13 @@ impl Listener {
}
}

pub const fn is_already_accepted(&self) -> bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

While I know the rest of the code is not consistent about this, having at least a minimal documentation string I think is a good idea for public APIs.

Ok(Box::new(s))
&Listener::TCP(Some(ref l), accepted) => {
if accepted {
unsafe { Ok(Box::new(TcpStream::from_raw_fd(l.as_raw_fd()))) }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Without digging into this code a lot more, there's a reason those functions are unsafe and that reason is exactly what looks like a bug here: The previous listener still thinks it owns the file descriptor.

We can avoid this by deconstructing into an OwnedFd like Box::new(TcpStream::from(l.into::<OwnedFd>())) or so.

But I think we need to back up on this, I'll comment on the original ticket.

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.

2 participants