* fhandler.h (class fhandler_socket): Remove has_been_closed member.
* fhandler_socket.cc (fhandler_socket::recvfrom): Revert to overlapped I/O. (fhandler_socket::recvmsg): Ditto. (fhandler_socket::sendto): Ditto. (fhandler_socket::sendmsg): Ditto. * net.cc (wsock_event::prepare): Ditto. (wsock_event::wait): Ditto. Evaluate overlapped result also after calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>). (wsock_event::release): Remove. * wsock_event.h: Revert to overlapped I/O.
This commit is contained in:
parent
81961a5001
commit
321ddf2422
|
@ -1,3 +1,17 @@
|
|||
2004-04-03 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler.h (class fhandler_socket): Remove has_been_closed member.
|
||||
* fhandler_socket.cc (fhandler_socket::recvfrom): Revert to
|
||||
overlapped I/O.
|
||||
(fhandler_socket::recvmsg): Ditto.
|
||||
(fhandler_socket::sendto): Ditto.
|
||||
(fhandler_socket::sendmsg): Ditto.
|
||||
* net.cc (wsock_event::prepare): Ditto.
|
||||
(wsock_event::wait): Ditto. Evaluate overlapped result also after
|
||||
calling CancelIo (thanks to Patrick Samson <p_samson@yahoo.com>).
|
||||
(wsock_event::release): Remove.
|
||||
* wsock_event.h: Revert to overlapped I/O.
|
||||
|
||||
2004-04-02 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* net.cc (wsock_event::release): Use NULL handle in call to
|
||||
|
|
|
@ -377,7 +377,6 @@ class fhandler_socket: public fhandler_base
|
|||
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
|
||||
char *sun_path;
|
||||
int had_connect_or_listen;
|
||||
int has_been_closed;
|
||||
|
||||
public:
|
||||
fhandler_socket ();
|
||||
|
|
|
@ -122,7 +122,7 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
|||
/* fhandler_socket */
|
||||
|
||||
fhandler_socket::fhandler_socket ()
|
||||
: fhandler_base (), sun_path (NULL), has_been_closed (0)
|
||||
: fhandler_base (), sun_path (NULL)
|
||||
{
|
||||
set_need_fork_fixup ();
|
||||
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
|
||||
|
@ -714,7 +714,7 @@ int
|
|||
fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
|
||||
struct sockaddr *from, int *fromlen)
|
||||
{
|
||||
int res = SOCKET_ERROR;
|
||||
int res;
|
||||
DWORD ret;
|
||||
|
||||
flags &= MSG_WINMASK;
|
||||
|
@ -726,28 +726,19 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags,
|
|||
{
|
||||
WSABUF wsabuf = { len, (char *) ptr };
|
||||
|
||||
if (is_nonblocking () || has_been_closed)
|
||||
res = WSARecvFrom (get_socket (), &wsabuf, 1, (ret = 0, &ret),
|
||||
(DWORD *) &flags, from, fromlen, NULL, NULL);
|
||||
if (is_nonblocking ())
|
||||
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
|
||||
from, fromlen,
|
||||
NULL, NULL);
|
||||
else
|
||||
{
|
||||
wsock_event wsock_evt;
|
||||
long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
|
||||
if (wsock_evt.prepare (get_socket (), evt))
|
||||
{
|
||||
do
|
||||
{
|
||||
res = WSARecvFrom (get_socket (), &wsabuf, 1,
|
||||
(ret = 0, &ret), (DWORD *) &flags,
|
||||
from, fromlen, NULL, NULL);
|
||||
}
|
||||
while (res == SOCKET_ERROR
|
||||
&& WSAGetLastError () == WSAEWOULDBLOCK
|
||||
&& !has_been_closed
|
||||
&& !(res = wsock_evt.wait (get_socket (),
|
||||
has_been_closed)));
|
||||
wsock_evt.release (get_socket ());
|
||||
}
|
||||
res = WSARecvFrom (get_socket (), &wsabuf, 1, &ret, (DWORD *) &flags,
|
||||
from, fromlen,
|
||||
wsock_evt.prepare (), NULL);
|
||||
|
||||
if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
|
||||
ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -785,7 +776,7 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
|
|||
struct sockaddr *from = (struct sockaddr *) msg->msg_name;
|
||||
int *fromlen = from ? &msg->msg_namelen : NULL;
|
||||
|
||||
int res = SOCKET_ERROR;
|
||||
int res;
|
||||
|
||||
if (!winsock2_active)
|
||||
{
|
||||
|
@ -852,29 +843,21 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags, ssize_t tot)
|
|||
|
||||
DWORD ret;
|
||||
|
||||
if (is_nonblocking () || has_been_closed)
|
||||
if (is_nonblocking ())
|
||||
res = WSARecvFrom (get_socket (),
|
||||
wsabuf, iovcnt, (ret = 0, &ret), (DWORD *) &flags,
|
||||
from, fromlen, NULL, NULL);
|
||||
wsabuf, iovcnt, &ret, (DWORD *) &flags,
|
||||
from, fromlen,
|
||||
NULL, NULL);
|
||||
else
|
||||
{
|
||||
wsock_event wsock_evt;
|
||||
long evt = (FD_CLOSE | ((flags & MSG_OOB) ? FD_OOB : FD_READ));
|
||||
if (wsock_evt.prepare (get_socket (), evt))
|
||||
{
|
||||
do
|
||||
{
|
||||
res = WSARecvFrom (get_socket (), wsabuf, iovcnt,
|
||||
(ret = 0, &ret), (DWORD *) &flags,
|
||||
from, fromlen, NULL, NULL);
|
||||
}
|
||||
while (res == SOCKET_ERROR
|
||||
&& WSAGetLastError () == WSAEWOULDBLOCK
|
||||
&& !has_been_closed
|
||||
&& !(res = wsock_evt.wait (get_socket (),
|
||||
has_been_closed)));
|
||||
wsock_evt.release (get_socket ());
|
||||
}
|
||||
res = WSARecvFrom (get_socket (),
|
||||
wsabuf, iovcnt, &ret, (DWORD *) &flags,
|
||||
from, fromlen,
|
||||
wsock_evt.prepare (), NULL);
|
||||
|
||||
if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
|
||||
ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
|
||||
}
|
||||
|
||||
if (res == SOCKET_ERROR)
|
||||
|
@ -917,9 +900,9 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
|
|||
sockaddr_in sin;
|
||||
|
||||
if (to && !get_inet_addr (to, tolen, &sin, &tolen))
|
||||
return -1;
|
||||
return SOCKET_ERROR;
|
||||
|
||||
int res = SOCKET_ERROR;
|
||||
int res;
|
||||
DWORD ret;
|
||||
|
||||
if (!winsock2_active)
|
||||
|
@ -930,35 +913,21 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
|
|||
{
|
||||
WSABUF wsabuf = { len, (char *) ptr };
|
||||
|
||||
if (is_nonblocking () || has_been_closed)
|
||||
res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
|
||||
if (is_nonblocking ())
|
||||
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
|
||||
flags & MSG_WINMASK,
|
||||
(to ? (const struct sockaddr *) &sin : NULL), tolen,
|
||||
NULL, NULL);
|
||||
else
|
||||
{
|
||||
wsock_event wsock_evt;
|
||||
if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
|
||||
{
|
||||
do
|
||||
{
|
||||
res = WSASendTo (get_socket (), &wsabuf, 1, (ret = 0, &ret),
|
||||
flags & MSG_WINMASK,
|
||||
(to ? (const struct sockaddr *) &sin : NULL),
|
||||
tolen, NULL, NULL);
|
||||
if (res != SOCKET_ERROR
|
||||
|| WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
break;
|
||||
if (ret > 0)
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!(res = wsock_evt.wait (get_socket (), has_been_closed))
|
||||
&& !has_been_closed);
|
||||
wsock_evt.release (get_socket ());
|
||||
}
|
||||
res = WSASendTo (get_socket (), &wsabuf, 1, &ret,
|
||||
flags & MSG_WINMASK,
|
||||
(to ? (const struct sockaddr *) &sin : NULL), tolen,
|
||||
wsock_evt.prepare (), NULL);
|
||||
|
||||
if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
|
||||
ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -998,7 +967,7 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
|
|||
struct iovec *const iov = msg->msg_iov;
|
||||
const int iovcnt = msg->msg_iovlen;
|
||||
|
||||
int res = SOCKET_ERROR;
|
||||
int res;
|
||||
|
||||
if (!winsock2_active)
|
||||
{
|
||||
|
@ -1067,34 +1036,21 @@ fhandler_socket::sendmsg (const struct msghdr *msg, int flags, ssize_t tot)
|
|||
|
||||
DWORD ret;
|
||||
|
||||
if (is_nonblocking () || has_been_closed)
|
||||
res = WSASendTo (get_socket (), wsabuf, iovcnt, (ret = 0, &ret),
|
||||
flags, (struct sockaddr *) msg->msg_name,
|
||||
msg->msg_namelen, NULL, NULL);
|
||||
if (is_nonblocking ())
|
||||
res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
|
||||
(struct sockaddr *) msg->msg_name,
|
||||
msg->msg_namelen,
|
||||
NULL, NULL);
|
||||
else
|
||||
{
|
||||
wsock_event wsock_evt;
|
||||
if (wsock_evt.prepare (get_socket (), FD_CLOSE | FD_WRITE))
|
||||
{
|
||||
do
|
||||
{
|
||||
res = WSASendTo (get_socket (), wsabuf, iovcnt,
|
||||
(ret = 0, &ret), flags,
|
||||
(struct sockaddr *) msg->msg_name,
|
||||
msg->msg_namelen, NULL, NULL);
|
||||
if (res != SOCKET_ERROR
|
||||
|| WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
break;
|
||||
if (ret > 0)
|
||||
{
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!(res = wsock_evt.wait (get_socket (), has_been_closed))
|
||||
&& !has_been_closed);
|
||||
wsock_evt.release (get_socket ());
|
||||
}
|
||||
res = WSASendTo (get_socket (), wsabuf, iovcnt, &ret, flags,
|
||||
(struct sockaddr *) msg->msg_name,
|
||||
msg->msg_namelen,
|
||||
wsock_evt.prepare (), NULL);
|
||||
|
||||
if (res == SOCKET_ERROR && WSAGetLastError () == WSA_IO_PENDING)
|
||||
ret = res = wsock_evt.wait (get_socket (), (DWORD *) &flags);
|
||||
}
|
||||
|
||||
if (res == SOCKET_ERROR)
|
||||
|
|
|
@ -50,83 +50,59 @@ extern "C"
|
|||
int sscanf (const char *, const char *, ...);
|
||||
} /* End of "C" section */
|
||||
|
||||
bool
|
||||
wsock_event::prepare (int sock, long event_mask)
|
||||
LPWSAOVERLAPPED
|
||||
wsock_event::prepare ()
|
||||
{
|
||||
WSASetLastError (0);
|
||||
if ((event = WSACreateEvent ()) == WSA_INVALID_EVENT)
|
||||
debug_printf ("WSACreateEvent: %E");
|
||||
else if (WSAEventSelect (sock, event, event_mask) == SOCKET_ERROR)
|
||||
{
|
||||
debug_printf ("WSAEventSelect: %E");
|
||||
WSACloseEvent (event);
|
||||
event = WSA_INVALID_EVENT;
|
||||
}
|
||||
return event != WSA_INVALID_EVENT;
|
||||
}
|
||||
LPWSAOVERLAPPED ret = NULL;
|
||||
|
||||
int
|
||||
wsock_event::wait (int sock, int &closed)
|
||||
{
|
||||
int ret = SOCKET_ERROR;
|
||||
int wsa_err = 0;
|
||||
WSAEVENT ev[2] = { event, signal_arrived };
|
||||
switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
|
||||
SetLastError (0);
|
||||
if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
|
||||
{
|
||||
case WSA_WAIT_EVENT_0:
|
||||
WSANETWORKEVENTS evts;
|
||||
if (!WSAEnumNetworkEvents (sock, event, &evts))
|
||||
{
|
||||
if (evts.lNetworkEvents & FD_READ)
|
||||
{
|
||||
if (evts.iErrorCode[FD_READ_BIT])
|
||||
wsa_err = evts.iErrorCode[FD_READ_BIT];
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
else if (evts.lNetworkEvents & FD_WRITE)
|
||||
{
|
||||
if (evts.iErrorCode[FD_WRITE_BIT])
|
||||
wsa_err = evts.iErrorCode[FD_WRITE_BIT];
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
if (evts.lNetworkEvents & FD_CLOSE)
|
||||
{
|
||||
closed = 1;
|
||||
if (!wsa_err)
|
||||
{
|
||||
if (evts.iErrorCode[FD_CLOSE_BIT])
|
||||
wsa_err = evts.iErrorCode[FD_CLOSE_BIT];
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (wsa_err)
|
||||
WSASetLastError (wsa_err);
|
||||
}
|
||||
break;
|
||||
case WSA_WAIT_EVENT_0 + 1:
|
||||
WSASetLastError (WSAEINTR);
|
||||
break;
|
||||
default:
|
||||
WSASetLastError (WSAEFAULT);
|
||||
memset (&ovr, 0, sizeof ovr);
|
||||
ovr.hEvent = event;
|
||||
ret = &ovr;
|
||||
}
|
||||
else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
|
||||
WSASetLastError (0);
|
||||
|
||||
debug_printf ("%d = wsock_event::prepare ()", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
wsock_event::release (int sock)
|
||||
int
|
||||
wsock_event::wait (int socket, LPDWORD flags)
|
||||
{
|
||||
int last_err = WSAGetLastError ();
|
||||
/* KB 168349: NT4 fails if the event parameter is not NULL. */
|
||||
WSAEventSelect (sock, NULL, 0);
|
||||
int ret = SOCKET_ERROR;
|
||||
WSAEVENT ev[2] = { event, signal_arrived };
|
||||
DWORD len;
|
||||
|
||||
switch (WSAWaitForMultipleEvents (2, ev, FALSE, WSA_INFINITE, FALSE))
|
||||
{
|
||||
case WSA_WAIT_EVENT_0:
|
||||
if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags))
|
||||
ret = (int) len;
|
||||
break;
|
||||
case WSA_WAIT_EVENT_0 + 1:
|
||||
if (!CancelIo ((HANDLE) socket))
|
||||
{
|
||||
debug_printf ("CancelIo() %E, fallback to blocking io");
|
||||
WSAGetOverlappedResult (socket, &ovr, &len, TRUE, flags);
|
||||
}
|
||||
else if (WSAGetOverlappedResult (socket, &ovr, &len, FALSE, flags)
|
||||
&& len > 0)
|
||||
ret = (int) len;
|
||||
else
|
||||
WSASetLastError (WSAEINTR);
|
||||
break;
|
||||
case WSA_WAIT_FAILED:
|
||||
break;
|
||||
default: /* Should be impossible. *LOL* */
|
||||
WSASetLastError (WSAEFAULT);
|
||||
break;
|
||||
}
|
||||
WSACloseEvent (event);
|
||||
unsigned long non_block = 0;
|
||||
if (ioctlsocket (sock, FIONBIO, &non_block))
|
||||
debug_printf ("return to blocking failed: %d", WSAGetLastError ());
|
||||
else
|
||||
WSASetLastError (last_err);
|
||||
event = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
WSADATA wsadata;
|
||||
|
|
|
@ -14,13 +14,19 @@ details. */
|
|||
class wsock_event
|
||||
{
|
||||
WSAEVENT event;
|
||||
WSAOVERLAPPED ovr;
|
||||
public:
|
||||
wsock_event () : event (NULL) {};
|
||||
~wsock_event ()
|
||||
{
|
||||
if (event)
|
||||
WSACloseEvent (event);
|
||||
event = NULL;
|
||||
};
|
||||
|
||||
/* The methods are implemented in net.cc */
|
||||
bool prepare (int sock, long event_mask);
|
||||
int wait (int sock, int &closed);
|
||||
void release (int sock);
|
||||
LPWSAOVERLAPPED prepare ();
|
||||
int wait (int socket, LPDWORD flags);
|
||||
};
|
||||
|
||||
#endif /* __WSOCK_EVENT_H__ */
|
||||
|
|
Loading…
Reference in New Issue