-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Add initial named pipes support #3388
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only quickly looked, but I have this comment.
tokio/src/net/windows/named_pipe.rs
Outdated
Poll::Ready(Ok(())) | ||
} | ||
|
||
fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<()>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call self.disconnect()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems yes but only for the server side. For me pool_shutdown
itself is a bit diverges with the fact, that it's possible for NamedPipe
to be reconnected after disconnect()
, so I'm not sure about this. I'll try to change the API to fix this.
tokio/src/net/windows/named_pipe.rs
Outdated
.read(true) | ||
.write(true) | ||
.custom_flags(FILE_FLAG_OVERLAPPED) | ||
.open(addr.as_ref())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, the goal here is to omit the FILE_FLAG_FIRST_PIPE_INSTANCE
to make this open-only and not create-only?
We should probably add this to mio at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add this to mio at some point.
Yeah, I meant exactly this saying that mio's interface limits the miow named pipes implementation (miow supports this flag). I wonder if it's OK to simply add From<miow::NamedPIpe> for NamedPipe
into mio to not to rewrite miow's NamedPipeBuilder
🤔.
Regarding this open
call – I believe FILE_FLAG_FIRST_PIPE_INSTANCE
is irrelevant here, since this call leads to OpenFile2
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regarding this open call – I believe FILE_FLAG_FIRST_PIPE_INSTANCE is irrelevant here, since this call leads to OpenFile2.
Sorry for the confusion. I was asking to clarify if I read correctly that the intent with creating the file object ourselves was to avoid this flag. Since miow would otherwise set it (and we don't have a way of controlling that through mio).
tokio/src/net/windows/named_pipe.rs
Outdated
let file = OpenOptions::new() | ||
.read(true) | ||
.write(true) | ||
.custom_flags(FILE_FLAG_OVERLAPPED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be setting security_qos_flags
here?
cdc1137
to
0793217
Compare
@udoprog, @Darksonn, @fussybeaver, please see updated PR message. |
0793217
to
c9f5fe4
Compare
I need to better understand the behavior of named pipes. Do they follow the client/server model exclusively? It looks like they can be configured to be unidirectional or bidirectional? Is there anything else to know? |
The actual set of features is wider than exposed by this PR. It includes:
This list may not be complete since I'm not an expert. |
Can someone here comment on how/if this PR will allow serial ports to be integrated in Tokio on Windows? I would be happy to do some testing if its believed this PR now makes this possible.
|
Hey All, Looking to do a communication with a server over named pipes, and unfortunately as seen above it's broken with tokio 0.3 and above (including 1.0). Curious if there's any help with testing, code, review, etc. I can do to help push this along. Thanks for all your owrk! |
Hi, @Mythra.
I'm interested in both testing and code/design review. Any feedback would be appreciated. |
Hey, I've been testing this for my needs (on my own branch I just cherrypicked your commit), and I'd like to report it works just like I'd expect it too. I won't speak too much on the API Front (as i'm only using a client to a pre-existing named pipe, and am also not a maintainer of tokio), but for comparison between named pipes, and UDS support the code looks effectively the same (in fact I could probably combine them down to the same structures, with just |
Client-side API works fine from my side as well (all windows integration tests passing) |
Is there any reasonable alternative to integrating this? I don't see how it would work now that you can't hand |
To be clear, we do want to support named pipes. We just haven't really had the time to look into how it would work. |
The alternative I see is to integrate a clone of a feature-complete low-level API (say this one) into the |
We use Named Pipes in production in an extremely similar way to Unix sockets, so much so that it's almost a drop-in replacement. We run gRPC over Named Pipes on Windows, and UDS on macOS. Works like a charm. But we can't update to Tokio 1.0 because of this lack of support. As far as API design is concerned, if it behaves as server-client UDS would, that should be sufficient for the majority of real-world named pipe use cases. For the rest, I imagine it can be handled by the ecosystem at large so long as a raw file descriptor is accessible from the API. |
I agree completely with @bbqsrc. We also use it pretty identical to UDS. With the addition that we must be able to set security attributes on the server end to limit access. |
Third on using it as an alternative to UDS, but it's definitely worth investigating if the relative weirdness of the API is something that can be handled ideally by tokio or should be exposed for a higher level library. Some thoughts, in no particular order: The overlapped IO example creates a set of instances then waits for them to connect in parallel, is this functionally something that a user could care about, or can tokio pick the "right" option here? Is this best exposed as a parameter on on I suspect, however, that a lot of the different ways named pipes can work are for allowing apps to use the right level of simplicity or performance for their app, and that there are pretty easy ways for tokio to simply get this right and tuck away the scary bits. Functionality differences, like the Buffer sizes, security etc, all seem like they would want an equivalent to Interestingly, on the client side, the "only" thing actually needed is to add "real" async support to Despite being the common use case, I think tokio shouldn't provide anything to hide the differences between UDS and named pipes itself, Dealing with establishing that there's a server on the other end, exclusive serving, security, will all have specific approaches that will be in use already or otherwise better suited. |
Yes. To clarify my position, I did not mean that the interface should look the same as UDS. I meant that the feature set necessary for a Named Pipes "stable release" to my mind would be the equivalent features to UDS, regardless of the API it reveals. |
I would like to echo what others said - simple client/server with security attributes is what would allow https://github.com/nikvolf/parity-tokio-ipc (simple, unified UDS/named pipes interface) to upgrade to Tokio 1.0. See https://github.com/NikVolf/parity-tokio-ipc/blob/master/src/win.rs for some prior implementation (we basically reimplement stuff on top of |
And another implementation we use: https://github.com/bbqsrc/tokio-named-pipe (not to be confused with tokio-named-pipes above, hehe) |
Can you clarify these use cases? We need a clear understanding of the use cases in order to model an API. I think the best strategy for moving forward here is to list out the use cases we want the API to support. This probably should be done in a separate issue. Once we are in agreement w/ the cases we want to cover, then we can start focusing on an API proposal. |
Hi. The new version introduces It won't work without tokio-rs/mio#1461, so mio version bumped to 0.7.9 (see the Regarding connection order. It is possible to conclude empirically, that clients will connect in natural order (see the |
I just tested this in our SQL Server client Tiberius. Connecting to a pipe and passing this |
Would really love to have this support, what is left for it to be merged? :) |
Hmm, trying this out, it seems that client/server functionality only works when the server and client is spawned inside the same executable. When the server is a separate executable, It does however when client and server are in the same process. |
See both this PR, and the design issue are stalled again. What's left to be done, what can be helped with? Maintaining a fork of this is definitely starting to have it's toll. |
I think the main problem is that to review a PR that implements this, I need to have some understanding of what kind of features the windows API has. I don't want to end up with a sub-par API that only supports some of the use-cases, or one that maps poorly to the underlying windows API. Being able to evaluate this will take a time investment from me that I haven't been able to find the time for yet. There's also the question of crate choice of |
That makes sense, it's incredibly unfortunate, but I understand there's only so much time in the day. Thanks for all you do! |
I just found out about the fact that windows has native support for UDS for about 2 years now! Can't find an actual release notification, but everyone seems to agree that it works from Windows 1803, and Might be worth enabling that first (assuming it doesn't already work!), if adding native named pipes is too much work. |
I'd really dislike prioritizing AF_Unix windows support, for named pipe support. When many apps I've checked as well as cases mentioned in this PR can't use AF_Unix. If contribution time on Windows is low (which seems to be the core problem), using that valuable time doing something not well supported seems not worth it. Especially considering this PR blocks many apps from upgrading Tokio as this used to work. Albeit with an interface that was deemed undesirable. As an example, Docker does not support this even after its release (my use case along with I know two others who fork): moby/moby#36442 MSSQL another large use case (and the opener of the PR) also do not support AF_Unix. While obviously some apps do support af_unix I think this is overall a relatively minor use case, and while an issue should be opened. I'd plead that this PR be prioritized above sockets even if it's "quick". |
Sure, I was wondering if it was close to "just remove the |
Just a very high level thought on the stuck nature of this pull request and how we might be able to unstuck it. It might be easier right now to temporarily abandon the client / server stream architecture that's being proposed and focus more on exposing an API which more closely reflects the underlying low-level API - even if it ends up having unsafe edges (like how the constructor that can take That raises another issue in that we need access to a named pipe builder to give users of the API somewhat idiomatic access to a full range of capabilities. And due to the stability guarantees we can't re-export types which are provided by mio or miow, so it would have to live in Tokio until both of them are stable. One way to move forward here could be to copy the builder that's in miow so it can be exported and subject to the stability guarantees of Tokio. I would at least be able to review such a PR, since I'm more familiar with how the raw API works, and less so with the proposed high-level abstractions. What do you think @blackbeam @Darksonn? |
It's also worth noting that |
We can always define our own version of Maybe the first step is to list out all syscalls one can make w/ a named pipe. |
As someone that has spent too long staring at the named pipe docs, the miow API is much clearer and is well designed as a "native" API wrapper, at least as an introduction. The main thing that looks like its missing us create flags, mainly message oriented pipes (vs the "normal" byte stream), which have identical usage other than a guarantee on the packets not getting merged, AFAIK. In particular it preserves the odd design of creating multiple servers, one for each connection, optionally with the first being created exclusively. |
Note also that |
Closing as #3760 was merged. |
I would like to thank everyone for helping us understand the right design for named pipes! |
Bump to Tokio 1.0 Closes #1695 Closes #1693 Just enabled by tokio-rs/tokio#3388. Work in progress to prune winapi 0.2, still needs patches upstreamed that migrate `parity-tokio-ipc` and `jsonrpc-*` crates to Tokio 1.0. Let's see what CI has to say, first. Blocked on: - [x] paritytech/parity-tokio-ipc#32 - [x] paritytech/jsonrpc#628
This PR adds basic named pipes support.
Motivation
blackbeam/mysql_async#132
Solution
Implementation directly uses
miow::NamedPipeBuilder
to avoid making a PR formio
.It provides two public types:
NamedPipeServer
– which is a server implementation with the familiaraccept()
method.NamedPipe
– that represents client or server connection.NamedPipeServer
will hold at least one free instance of a pipe to maintain its existence.Mutex
is used withinaccept()
(only formem::swap
) to keep it shared.NamedPipeServer::new()
will create the first instance withFILE_FLAG_FIRST_PIPE_INSTANCE
flag to avoid named pipe instance creation race condition.NamedPipe
wrapsmio::NamedPipe
and provides theconnect()
method for client-side connections.connect()
will wait for a server instance using the approach similar to a one used in .NET, namely it'll callWaitNamedPipe
with default timeout using thespawn_blocking
(I couldn't find a better solution). Unlike .NET,connect()
won't wait if pipe doesn't exist and will error immediately.@udoprog, regarding
disconnect()
–NamedPipe
doesn't provide it since it won't play well withNamedPipeServer
, one should simply drop an instance. Also I don't think that we should call it inpoll_shutdown
.@fussybeaver, regarding
security_qos_flags
- implementation unconditionally addsSECURITY_IDENTIFICATION
Other thoughts
Maybe it's too high level.
Related issues
#3118