4176. [bug] Address race issues with lwresd. [RT #40284]

(cherry picked from commit 563878539a)
This commit is contained in:
Mark Andrews
2015-08-14 15:47:53 +10:00
parent 52537c8ce4
commit 1b52fc8df0
3 changed files with 74 additions and 23 deletions

View File

@@ -1,3 +1,5 @@
4176. [bug] Address race issues with lwresd. [RT #40284]
4175. [bug] TKEY with GSS-API keys needed bigger buffers.
[RT #40333]

View File

@@ -186,6 +186,7 @@ struct ns_lwdclientmgr {
lwres_context_t *lwctx; /*%< lightweight proto context */
isc_task_t *task; /*%< owning task */
unsigned int flags;
isc_mutex_t lock;
ISC_LINK(ns_lwdclientmgr_t) link;
ISC_LIST(ns_lwdclient_t) idle; /*%< idle client slots */
ISC_LIST(ns_lwdclient_t) running; /*%< running clients */

View File

@@ -59,12 +59,16 @@ ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
ns_lwdclientmgr_t *cm;
ns_lwdclient_t *client;
unsigned int i;
isc_result_t result = ISC_R_FAILURE;
isc_result_t result;
cm = isc_mem_get(lwresd->mctx, sizeof(ns_lwdclientmgr_t));
if (cm == NULL)
return (ISC_R_NOMEMORY);
result = isc_mutex_init(&cm->lock);
if (result != ISC_R_SUCCESS)
goto freecm;
cm->listener = NULL;
ns_lwreslistener_attach(listener, &cm->listener);
cm->mctx = lwresd->mctx;
@@ -78,10 +82,10 @@ ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
ISC_LIST_INIT(cm->idle);
ISC_LIST_INIT(cm->running);
if (lwres_context_create(&cm->lwctx, cm->mctx,
ns__lwresd_memalloc, ns__lwresd_memfree,
LWRES_CONTEXT_SERVERMODE)
!= ISC_R_SUCCESS)
result = lwres_context_create(&cm->lwctx, cm->mctx,
ns__lwresd_memalloc, ns__lwresd_memfree,
LWRES_CONTEXT_SERVERMODE);
if (result != ISC_R_SUCCESS)
goto errout;
for (i = 0; i < nclients; i++) {
@@ -96,8 +100,10 @@ ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
/*
* If we could create no clients, clean up and return.
*/
if (ISC_LIST_EMPTY(cm->idle))
if (ISC_LIST_EMPTY(cm->idle)) {
result = ISC_R_NOMEMORY;
goto errout;
}
result = isc_task_create(taskmgr, 0, &cm->task);
if (result != ISC_R_SUCCESS)
@@ -130,6 +136,9 @@ ns_lwdclientmgr_create(ns_lwreslistener_t *listener, unsigned int nclients,
if (cm->lwctx != NULL)
lwres_context_destroy(&cm->lwctx);
DESTROYLOCK(&cm->lock);
freecm:
isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
return (result);
}
@@ -139,11 +148,14 @@ lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) {
ns_lwdclient_t *client;
ns_lwreslistener_t *listener;
if (!SHUTTINGDOWN(cm))
LOCK(&cm->lock);
if (!SHUTTINGDOWN(cm)) {
UNLOCK(&cm->lock);
return;
}
/*
* run through the idle list and free the clients there. Idle
* Run through the idle list and free the clients there. Idle
* clients do not have a recv running nor do they have any finds
* or similar running.
*/
@@ -156,14 +168,20 @@ lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) {
client = ISC_LIST_HEAD(cm->idle);
}
if (!ISC_LIST_EMPTY(cm->running))
if (!ISC_LIST_EMPTY(cm->running)) {
UNLOCK(&cm->lock);
return;
}
UNLOCK(&cm->lock);
lwres_context_destroy(&cm->lwctx);
cm->view = NULL;
isc_socket_detach(&cm->sock);
isc_task_detach(&cm->task);
DESTROYLOCK(&cm->lock);
listener = cm->listener;
ns_lwreslistener_unlinkcm(listener, cm);
ns_lwdclient_log(50, "destroying manager %p", cm);
@@ -225,8 +243,10 @@ ns_lwdclient_recv(isc_task_t *task, isc_event_t *ev) {
NS_LWDCLIENT_SETRECVDONE(client);
LOCK(&cm->lock);
INSIST((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0);
cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
UNLOCK(&cm->lock);
ns_lwdclient_log(50,
"event received: task %p, length %u, result %u (%s)",
@@ -274,26 +294,42 @@ ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
ns_lwdclient_t *client;
isc_result_t result;
isc_region_t r;
isc_boolean_t destroy = ISC_FALSE;
LOCK(&cm->lock);
if (SHUTTINGDOWN(cm)) {
lwdclientmgr_destroy(cm);
return (ISC_R_SUCCESS);
destroy = ISC_TRUE;
result = ISC_R_SUCCESS;
goto unlock;
}
/*
* If a recv is already running, don't bother.
*/
if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0)
return (ISC_R_SUCCESS);
if ((cm->flags & NS_LWDCLIENTMGR_FLAGRECVPENDING) != 0) {
result = ISC_R_SUCCESS;
goto unlock;
}
/*
* If we have no idle slots, just return success.
*/
client = ISC_LIST_HEAD(cm->idle);
if (client == NULL)
return (ISC_R_SUCCESS);
if (client == NULL) {
result = ISC_R_SUCCESS;
goto unlock;
}
INSIST(NS_LWDCLIENT_ISIDLE(client));
/*
* Set the flag to say there is a recv pending. If isc_socket_recv
* fails we will clear the flag otherwise it will be cleared by
* ns_lwdclient_recv.
*/
cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;
/*
* Issue the recv. If it fails, return that it did.
*/
@@ -301,13 +337,10 @@ ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
r.length = LWRES_RECVLENGTH;
result = isc_socket_recv(cm->sock, &r, 0, cm->task, ns_lwdclient_recv,
client);
if (result != ISC_R_SUCCESS)
return (result);
/*
* Set the flag to say we've issued a recv() call.
*/
cm->flags |= NS_LWDCLIENTMGR_FLAGRECVPENDING;
if (result != ISC_R_SUCCESS) {
cm->flags &= ~NS_LWDCLIENTMGR_FLAGRECVPENDING;
goto unlock;
}
/*
* Remove the client from the idle list, and put it on the running
@@ -317,7 +350,13 @@ ns_lwdclient_startrecv(ns_lwdclientmgr_t *cm) {
ISC_LIST_UNLINK(cm->idle, client, link);
ISC_LIST_APPEND(cm->running, client, link);
return (ISC_R_SUCCESS);
unlock:
UNLOCK(&cm->lock);
if (destroy)
lwdclientmgr_destroy(cm);
return (result);
}
static void
@@ -335,6 +374,7 @@ lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
* clients do not have a recv running nor do they have any finds
* or similar running.
*/
LOCK(&cm->lock);
client = ISC_LIST_HEAD(cm->idle);
while (client != NULL) {
ns_lwdclient_log(50, "destroying client %p, manager %p",
@@ -343,6 +383,7 @@ lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
isc_mem_put(cm->mctx, client, sizeof(*client));
client = ISC_LIST_HEAD(cm->idle);
}
UNLOCK(&cm->lock);
/*
* Cancel any pending I/O.
@@ -353,6 +394,7 @@ lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
* Run through the running client list and kill off any finds
* in progress.
*/
LOCK(&cm->lock);
client = ISC_LIST_HEAD(cm->running);
while (client != NULL) {
if (client->find != client->v4find
@@ -367,6 +409,8 @@ lwdclientmgr_shutdown_callback(isc_task_t *task, isc_event_t *ev) {
cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
UNLOCK(&cm->lock);
isc_event_free(&ev);
}
@@ -387,8 +431,10 @@ ns_lwdclient_stateidle(ns_lwdclient_t *client) {
INSIST(client->v4find == NULL);
INSIST(client->v6find == NULL);
LOCK(&cm->lock);
ISC_LIST_UNLINK(cm->running, client, link);
ISC_LIST_PREPEND(cm->idle, client, link);
UNLOCK(&cm->lock);
NS_LWDCLIENT_SETIDLE(client);
@@ -464,5 +510,7 @@ ns_lwdclient_initialize(ns_lwdclient_t *client, ns_lwdclientmgr_t *cmgr) {
client->pktinfo_valid = ISC_FALSE;
LOCK(&cmgr->lock);
ISC_LIST_APPEND(cmgr->idle, client, link);
UNLOCK(&cmgr->lock);
}