Multiple handles to same pipe can behave incorrectly
To read or write to the same pipe in multiple places, Pipe::clone must be used to share the pipe. This is because pipe instances contain an internal Arc which will maintain the raw handle to the pipe until the last instance is dropped. Creating 2 separate handles to the same pipe ~~is currently undefined behavior, and~~ will work differently per-platform.
A possible solution to this would be to maintain a global table of pipe handles that all instances refer to. This would have to be protected behind an RwLock, which is potentially not ideal. If a better architecture can solve this, I'd prefer to go down that road. Otherwise, that may be the necessary implementation.
I'd like to raise several (maybe dumb) questions/concerns regarding this issue:
- How does that affect multiple processes accessing the pipe (for example, different binaries for server and client, maybe even using different languages and libraries)
- If 1 is different than the "multiple thread case", in what way? Shoudn't it, from an user perspective at least, be the same?
- If 1 is also UB, isn't that a major problem, since the principal use-case for this library is IPC, and cloning is not usually possible between different processes, programs or even languages?
Actually, these are good questions. While this will work differently per-platform, I shouldn't have called it UB. I've stricken that statement through, as it's not entirely accurate.
The biggest issue is that Windows named pipes have a server and clients. This library initializes by checking to see if the pipe already has a server (Eg, is connected to a specific process), and deciding whether to open as a client or a server. As long as the server exists, a client can connect and begin duplex communications. When the server is closed (the Pipe instance is dropped), or its connected process ends, then any connected clients are forcefully disconnected. This results in something... Not intuitive.
The whole cloning thing shown here guards against that situation - but you're absolutely right that IPC is the point here and it doesn't really help to have a single-process solution.
On the Unix side this is just not an issue. A pipe is created then anything can get a handle to it and read/write or close the handle willy-nilly.
Ok, so maybe the solution is actually to acknowledge that client/server difference in the code rather than to hide it
I mean sure, it doesn't exist on unix, but if it exists on windows and my software must be cross-platform then I need to use the more restrictive subset anyway for compatibility
Alongside the cross-platform Pipe, you may introduce platform-specific alternatives for windows and unix that aren't restrictive (or maybe only a unix specific alternative since they exist on some recent windows 10 versions)
Concur with this. The right solution seens to be to provide a restricted API cross-platform, as well as a more open API for specific platforms