Commit 5857247d authored by Evan Hunt's avatar Evan Hunt
Browse files

2758. [bug] win32: Added a workaround for a windows 2008 bug

			that could cause the UDP client handler to shut
			down. [RT #19176]
parent 7fe4b044
2758. [bug] win32: Added a workaround for a windows 2008 bug
that could cause the UDP client handler to shut
down. [RT #19176]
2757. [bug] dig: assertion failure could occur in connect
timeout. [RT #20599]
......
......@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: socket.c,v 1.80 2009/09/25 23:48:11 tbox Exp $ */
/* $Id: socket.c,v 1.81 2009/11/10 18:31:47 each Exp $ */
/* This code uses functions which are only available on Server 2003 and
* higher, and Windows XP and higher.
......@@ -272,6 +272,7 @@ struct isc_socket {
unsigned int pending_accept; /* Number of outstanding accept() calls. */
unsigned int state; /* Socket state. Debugging and consistency checking. */
int state_lineno; /* line which last touched state */
int in_recovery_cnt; /* avoid recovery loop. */
};
#define _set_state(sock, _state) do { (sock)->state = (_state); (sock)->state_lineno = __LINE__; } while (0)
......@@ -364,6 +365,8 @@ static void send_connectdone_event(isc_socket_t *sock, isc_socket_connev_t **cde
static void send_recvdone_abort(isc_socket_t *sock, isc_result_t result);
static void queue_receive_event(isc_socket_t *sock, isc_task_t *task, isc_socketevent_t *dev);
static void queue_receive_request(isc_socket_t *sock);
static void hard_recover_receive_request(isc_socket_t *sock);
static void recover_receive_request(isc_socket_t *sock, void **lplpo);
/*
* This is used to dump the contents of the sock structure
......@@ -716,6 +719,7 @@ queue_receive_request(isc_socket_t *sock) {
int total_bytes = 0;
int Result;
int Error;
isc_boolean_t need_recovering = ISC_FALSE;
WSABUF iov[1];
IoCompletionInfo *lpo;
isc_result_t isc_result;
......@@ -763,9 +767,39 @@ queue_receive_request(isc_socket_t *sock) {
sock->pending_recv++;
break;
case ERROR_HOST_UNREACHABLE:
if (sock->type == isc_sockettype_udp) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"WSARecvFrom ERROR_HOST_UNREACHABLE: trying to recover");
need_recovering = ISC_TRUE;
break;
} else
goto fail;
case WSAENETRESET:
if (sock->type == isc_sockettype_udp) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"WSARecvFrom WSAENETRESET: trying to recover");
need_recovering = ISC_TRUE;
break;
} else
goto fail;
case WSAECONNRESET:
if (sock->type == isc_sockettype_udp) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"WSARecvFrom WSAECONNRESET: trying to recover");
need_recovering = ISC_TRUE;
break;
} else
goto fail;
default:
fail:
isc_result = isc__errno2result(Error);
if (isc_result == ISC_R_UNEXPECTED)
if ((isc_result == ISC_R_UNEXPECTED) ||
(isc_result == ISC_R_CONNECTIONRESET) ||
(isc_result == ISC_R_HOSTUNREACH))
UNEXPECTED_ERROR(__FILE__, __LINE__,
"WSARecvFrom: Windows error code: %d, isc result %d",
Error, isc_result);
......@@ -780,6 +814,7 @@ queue_receive_request(isc_socket_t *sock) {
*/
sock->pending_iocp++;
sock->pending_recv++;
sock->in_recovery_cnt = 0;
}
socket_log(__LINE__, sock, NULL, IOEVENT,
......@@ -789,6 +824,41 @@ queue_receive_request(isc_socket_t *sock) {
sock->fd, Result, Error);
CONSISTENT(sock);
if (need_recovering)
recover_receive_request(sock, &lpo);
}
/*
* (placeholder) Hard recovery, doing nothing useful today
* (other than to avoid unlimited recursion).
*/
static void
hard_recover_receive_request(isc_socket_t *sock)
{
UNEXPECTED_ERROR(__FILE__, __LINE__,
"can't recover fd %d sock %p",
sock->fd, sock);
send_recvdone_abort(sock, ISC_R_UNEXPECTED);
}
/*
* Recovery from a Windows 2008 Server bug
* (WSARecvFrom() getting an ERROR_HOST_UNREACHABLE).
* Free the overlapped pointer and requeue a receive request.
*/
static void
recover_receive_request(isc_socket_t *sock, void **lplpo)
{
if (*lplpo != NULL)
HeapFree(hHeapHandle, 0, *lplpo);
*lplpo = NULL;
/* limit recursion to 20 */
if (sock->in_recovery_cnt++ < 20)
queue_receive_request(sock);
else
hard_recover_receive_request(sock);
}
static void
......@@ -866,7 +936,7 @@ make_nonblock(SOCKET fd) {
}
/*
* Windows 2000 systems incorrectly cause UDP sockets using WASRecvFrom
* Windows 2000 systems incorrectly cause UDP sockets using WSARecvFrom
* to not work correctly, returning a WSACONNRESET error when a WSASendTo
* fails with an "ICMP port unreachable" response and preventing the
* socket from using the WSARecvFrom in subsequent operations.
......@@ -1318,7 +1388,7 @@ completeio_send(isc_socket_t *sock, isc_socketevent_t *dev,
UNEXPECTED_ERROR(__FILE__, __LINE__, "completeio_send: %s: %s",
addrbuf, strbuf);
dev->result = isc__errno2result(send_errno);
return (DOIO_HARD);
return (DOIO_HARD);
}
/*
......@@ -1387,6 +1457,7 @@ startio_send(isc_socket_t *sock, isc_socketevent_t *dev, int *nbytes,
"bytes, err %d/%s",
sock->fd, *nbytes, *send_errno, strbuf);
}
status = DOIO_HARD;
goto done;
}
dev->result = ISC_R_SUCCESS;
......@@ -1431,6 +1502,7 @@ allocate_socket(isc_socketmgr_t *manager, isc_sockettype_t type,
sock->connected = 0;
sock->pending_connect = 0;
sock->bound = 0;
sock->in_recovery_cnt = 0;
memset(sock->name, 0, sizeof(sock->name)); // zero the name field
_set_state(sock, SOCK_INITIALIZED);
......@@ -2332,7 +2404,7 @@ SocketIoThread(LPVOID ThreadContext) {
/*
* Did the I/O operation complete?
*/
errstatus = WSAGetLastError();
errstatus = GetLastError();
isc_result = isc__errno2resultx(errstatus, __FILE__, __LINE__);
LOCK(&sock->lock);
......@@ -2343,8 +2415,32 @@ SocketIoThread(LPVOID ThreadContext) {
sock->pending_iocp--;
INSIST(sock->pending_recv > 0);
sock->pending_recv--;
if ((sock->type == isc_sockettype_udp) &&
(errstatus == ERROR_HOST_UNREACHABLE)) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"SOCKET_RECV ERROR_HOST_UNREACHABLE: trying to recover");
recover_receive_request(sock, &lpo);
break;
}
if ((sock->type == isc_sockettype_udp) &&
(errstatus == WSAENETRESET)) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"SOCKET_RECV WSAENETRESET: trying to recover");
recover_receive_request(sock, &lpo);
break;
}
if ((sock->type == isc_sockettype_udp) &&
(errstatus == WSAECONNRESET)) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"SOCKET_RECV WSAECONNRESET: trying to recover");
recover_receive_request(sock, &lpo);
break;
}
send_recvdone_abort(sock, isc_result);
if (isc_result == ISC_R_UNEXPECTED) {
if ((isc_result == ISC_R_UNEXPECTED) ||
((isc_result == ISC_R_CONNECTIONRESET) &&
(errstatus != ERROR_OPERATION_ABORTED)) ||
(isc_result == ISC_R_HOSTUNREACH)) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"SOCKET_RECV: Windows error code: %d, returning ISC error %d",
errstatus, isc_result);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment