Tag Windows socket handles so they can be distinguished from file handles in posix namespace. #23580
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #14233
To allow reading/writing from separate threads under windows, the socket needs to be opened with the flag WSA_FLAG_OVERLAPPED. If this is not done, then either the reading thread or writing thread will be blocked indefinitely.
However, setting this flag, means that windows.ReadFile and windows.WriteFile (as used in net.Stream), will fail with "The parameter is incorrect" on a socket opened for overlapped IO, unless they pass an OVERLAPPED structure. This would also require creating and waiting on an event for every read/write and handling the IO_PENDING error case, making this option very inefficient.
My solution is to tag socket handles so that the posix layer can determine the difference between file handles and socket handles. It then calls either ReadFile/WriteFile or WSASend/WSARecv based on the type of handle. There is no in-built way to do determine if a handle is a socket in Windows, but according to ntdefs.h:
I set the lower 1 bit of the handle if it was created as a socket. File handles and other handles are unaffected by this change.
To enable this change, the ws2_32 SOCKET type is changed to be a HANDLE. The tagging of the handles is done in std.posix so that if someone wants to use the raw windows or ws2_32 calls, they get the normal un-tagged windows behavior. Only handles created through the posix namespace will be tagged as sockets.
In posix, a check is performed in read() and write() to determine if it is a socket and then makes the appropriate call for the type of handle.
Finally in net.Stream it is no longer necessary to special-case the windows reads and writes. These can now be done using the posix functions.
This also enables windows user to open sockets with posix.socket and read and write to them with posix.read and posix.write, rather than using the net namesspace if they so desire..
The additional benefit is that WSARecv and WSASend support readv/writev semantics. So a future patch can change the posix readv/writev to use WSARecv/WSASend for sockets.