Daniel Walker diwalker@earthlink.net writes:
I noticed that WSAEnumNetworkEvents() was returning all events that had occurred and not just the events that had been selected with WSAEventsSelect(). Win98 will trigger the event object for all events but WSAEnumNetworkEvents() (in win98) would return zero if the event hadn't been selected. I was trying to gain compatibility with win98.
I'd suggest doing the masking in WSAEnumNetworkEvents then.
An FD_READ event with a zero buffer would mean that the other side closed the connection so it would be equivalent to a POLLHUP from poll() .. I didn't find an occasion when poll() actually returned POLLHUP when the socket closed, on Linux anyway. The application that I was testing got confused when recv() returned zero. Even though recv() can legally return zero, I think non-blocking applications are going to be looking for FD_CLOSE events as opposed to recv() returning zero.
But FIONREAD can return 0 bytes even when the socket isn't closed (for instance if another thread got the data first). You can only determine that it was really closed when you do the actual read. So I don't really see how we can avoid having recv() return zero; well maybe we can make it return EWOULDBLOCK and tell the server the connection is closed, but I'm not sure it's any better.
Alexandre Julliard wrote:
Daniel Walker diwalker@earthlink.net writes:
I noticed that WSAEnumNetworkEvents() was returning all events that had
occurred and not just the events that had been selected with WSAEventsSelect(). Win98 will trigger the event object for all events but WSAEnumNetworkEvents() (in win98) would return zero if the event hadn't been selected. I was trying to gain compatibility with win98.
I'd suggest doing the masking in WSAEnumNetworkEvents then.
Ok.
An FD_READ event with a zero buffer would mean that the other side
closed the connection so it would be equivalent to a POLLHUP from poll() .. I didn't find an occasion when poll() actually returned POLLHUP when the socket closed, on Linux anyway. The application that I was testing got confused when recv() returned zero. Even though recv() can legally return zero, I think non-blocking applications are going to be looking for FD_CLOSE events as opposed to recv() returning zero.
But FIONREAD can return 0 bytes even when the socket isn't closed (for instance if another thread got the data first). You can only determine that it was really closed when you do the actual read. So I don't really see how we can avoid having recv() return zero; well maybe we can make it return EWOULDBLOCK and tell the server the connection is closed, but I'm not sure it's any better.
The FIONREAD would happen before the application even knows there is a FD_READ event. This particular functionality is critical in my opinion .. I've never actually seen an FD_CLOSE event without this patch. If an application is looking for FD_CLOSE and never gets it then it's going to act unpredictably.
To improve on this patch we could only do the FIONREAD if the sock is in a non-blocking state. That's the only time that doing the FIONREAD would be an advantage. Also we wouldn't need to worry about screwing up blocking sockets. Even further, we could only do the FIONREAD if socket is non-blocking and looking for an FD_CLOSE event.
Daniel Walker