You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
hmelder opened this issue
Aug 18, 2022
· 1 comment
Labels
bugUse this tag for reporting bugs or issues that impede the software's normal functionality.windowsLabel issues that are specific to the Windows operating system with this tag.
The GSInetSocketStream/GSInet6SocketStream classes abstract platform-dependent networking APIs away and expose them via the standard NSStream interface. Each socket stream has an input (GSSocketInputStream) and an output stream (GSSocketOutputStream).
After opening a new socket, the socket is recorded and monitored. On POSIX compliant systems the socket file descriptor is used as the loop id GSSocketStream.m:1715. On Windows, the loop id is an event object which is set up to receive socket events. The event object is associated with the socket via the WSAEventSelect function.
Winsock2 Events
Windows only permits a single event object to be associated with a socket at any time. GSInetSocketInputStream coordinates two Windows event objects via the _dispatch method. If one stream is closed, the _dispatch method GSSocketStream.m:2041 automatically switches to the second (sibling) event object GSSocketStream.m:1926.
The _dispatch method discovers changes for the selected socket. On Windows, the WSAEnumNetWorkEvents function is used.
The GSInetOutput stream object is added to the Runloop after the socket receives a write event (FD_WRITE) GSSocketStream.m:2124. The NSStreamEventHasBytesAvailable notification is never send and the write stream remains open, causing an assertion.
First Bug Fix
WSAEnumNetworkEvents returns the value '0x03' in the lNetworkEvents field, indicating that the FD_READ and FD_WRITE flag is set. In this case the NSStreamEventHasBytesAvailable event should be send, but the FD_WRITE flag is also set. Fix:
diff --git a/Source/GSSocketStream.m b/Source/GSSocketStream.m
index 88a72ec43..e414c3ed7 100644
--- a/Source/GSSocketStream.m+++ b/Source/GSSocketStream.m@@ -2584,6 +2584,16 @@ setNonBlocking(SOCKET fd)
}
else
{
+ if (events.lNetworkEvents & FD_READ)+ {+ [_sibling _setStatus: NSStreamStatusOpen];+ while ([_sibling hasBytesAvailable]+ && [_sibling _unhandledData] == NO)+ {+ [_sibling _sendEvent: NSStreamEventHasBytesAvailable];+ }+ }+
if (events.lNetworkEvents & FD_WRITE)
{
/* Clear NSStreamStatusWriting if it was set */
@@ -2599,15 +2609,6 @@ setNonBlocking(SOCKET fd)
[self _sendEvent: NSStreamEventHasSpaceAvailable];
}
- if (events.lNetworkEvents & FD_READ)- {- [_sibling _setStatus: NSStreamStatusOpen];- while ([_sibling hasBytesAvailable]- && [_sibling _unhandledData] == NO)- {- [_sibling _sendEvent: NSStreamEventHasBytesAvailable];- }- }
if (events.lNetworkEvents & FD_CLOSE)
{
[self _setClosing: YES];
Example:
$ curl localhost:12345
This is the data in the first chunk
and this is the second one
consequence
hmelder
added
bug
Use this tag for reporting bugs or issues that impede the software's normal functionality.
windows
Label issues that are specific to the Windows operating system with this tag.
labels
Sep 9, 2023
bugUse this tag for reporting bugs or issues that impede the software's normal functionality.windowsLabel issues that are specific to the Windows operating system with this tag.
Brief Introduction
The GSInetSocketStream/GSInet6SocketStream classes abstract platform-dependent networking APIs away and expose them via the standard NSStream interface. Each socket stream has an input (GSSocketInputStream) and an output stream (GSSocketOutputStream).
After opening a new socket, the socket is recorded and monitored. On POSIX compliant systems the socket file descriptor is used as the loop id GSSocketStream.m:1715. On Windows, the loop id is an event object which is set up to receive socket events. The event object is associated with the socket via the WSAEventSelect function.
Winsock2 Events
Windows only permits a single event object to be associated with a socket at any time. GSInetSocketInputStream coordinates two Windows event objects via the _dispatch method. If one stream is closed, the _dispatch method GSSocketStream.m:2041 automatically switches to the second (sibling) event object GSSocketStream.m:1926.
The _dispatch method discovers changes for the selected socket. On Windows, the WSAEnumNetWorkEvents function is used.
First Bug
We use the keepalive test as an example:
Starting the server:
Log (GSInetServerStream is initialised and added to the default Runloop):
Sending a message to the server:
Log MSVC:
Log Debian aarch64:
The GSInetOutput stream object is added to the Runloop after the socket receives a write event (FD_WRITE) GSSocketStream.m:2124. The NSStreamEventHasBytesAvailable notification is never send and the write stream remains open, causing an assertion.
First Bug Fix
WSAEnumNetworkEvents returns the value '0x03' in the lNetworkEvents field, indicating that the FD_READ and FD_WRITE flag is set. In this case the NSStreamEventHasBytesAvailable event should be send, but the FD_WRITE flag is also set. Fix:
Example:
Log:
Second Bug
The socket is not closed and _dispatch in a loop.
The text was updated successfully, but these errors were encountered: