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;
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++) {
/*
* 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)
if (cm->lwctx != NULL)
lwres_context_destroy(&cm->lwctx);
+ DESTROYLOCK(&cm->lock);
+
+ freecm:
isc_mem_put(lwresd->mctx, cm, sizeof(*cm));
return (result);
}
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.
*/
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);
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)",
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.
*/
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
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
* 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",
isc_mem_put(cm->mctx, client, sizeof(*client));
client = ISC_LIST_HEAD(cm->idle);
}
+ UNLOCK(&cm->lock);
/*
* Cancel any pending I/O.
* 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
cm->flags |= NS_LWDCLIENTMGR_FLAGSHUTTINGDOWN;
+ UNLOCK(&cm->lock);
+
isc_event_free(&ev);
}
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);
client->pktinfo_valid = ISC_FALSE;
+ LOCK(&cmgr->lock);
ISC_LIST_APPEND(cmgr->idle, client, link);
+ UNLOCK(&cmgr->lock);
}