Folks,Humm... I'll ruminate on this some... there may be another solution. You sure the WSASend call is not returning a timeout expiration?
we have a number of real issues with the win32 implementation of sockets which I think I can fix over the next day or so, but I'm just dropping off this note early enough for folks to bitch^H^H^H^H^H comment.
Serious Problem #1: Blocking Socket, apr_sendv() invokes WSASend()
with NULL completion arguments... according to WinSock2 this should
be a sync, blocking send. Put a huge (4MB), mmap'ed region into that iovec, and it will be sent - BUT IT IS SENT ASYNC! So later we close the
socket and the transmission is aborted.
Solution? Apparently we just can't trust sync send/recv, and I guess
it is time to simply surrender and make them all async with a completion
event, irrespective of timeouts. Then wait on that event INFINITE or by the so_timeout value.
Question; do we simply use the socket itself as the event handle?
Should be fine as long as multiple threads never attempt to touch the socket at the same time. apr_sendfile uses the socket as the event handle and AFAIK it has never caused a problem.
I'd prefer to not use a seperate event handle (for performance reasons) unless we have a clear demonstrated fully thought out need to. MHO.Or do we create one event for each socket that we can later use for all sorts of goodness such as a WSAAsyncSelect()-style poll? Two threads won't be looking at the same socket, so I think an event handle in each apr_socket_t would be useful.
Serious Problem #2: Win32 doesn't support socket timeouts. We are using raw WSASend/WSARecv, blocking. This just isn't good.
Sure it does, just not the same way as most unix systems. Unix uses nonblocking i/o followed by a select to do timeout. This is horribly inefficient on Windows where sys call overhead is high. Windows uses the builtin setsockopt(SO_RCVTIMEOUT) timeout mechanisms (which are part of the BSD socket spec but is not implemented on Unix). If, as you are reporting, WSA* calls are not really working as they should, then we should probably just do them async and wait for the io completion.
Solution? Same as for #1 above.
Serious Problem #3: Using WaitForSingleObject() with our 'socket' timeout value is rather bogus - it would measure the total elapsed time, not the interval between packet transmissions.
Solution? Well, if WinSock2 had some sort of 'progress' indication, bytes sent or received so far for a completion-based request - then we could just sample and assure ourselves that something had happened. As it is we just can't do that. Effectively, it looks like any huge send over a slow wire will be timed out based on any sane setting for a timeout value.
That should not be the case. Last time I checked, I though we set the timeout then sent 64K (?) chunks then reset the timeout for the next 64k chunk. This is -eaxactly- what 1.3 does on Unix (where signals are used as the timeout mechanism). This has someone changed that w/o my noticing? I'll check later...
Bill