Commit 532989b2 authored by Andreas Gustafsson's avatar Andreas Gustafsson

initate command channel shutdown from the server task, not the

main task, to avoid race conditions; eliminate global variables in
controlconf.c
parent bdfb3735
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: controlconf.c,v 1.5 2001/05/07 21:57:25 gson Exp $ */
/* $Id: controlconf.c,v 1.6 2001/05/08 03:42:27 gson Exp $ */
#include <config.h>
......@@ -23,7 +23,6 @@
#include <isc/buffer.h>
#include <isc/event.h>
#include <isc/mem.h>
#include <isc/once.h>
#include <isc/result.h>
#include <isc/stdtime.h>
#include <isc/string.h>
......@@ -79,6 +78,7 @@ struct controlconnection {
};
struct controllistener {
ns_controls_t * controls;
isc_mem_t * mctx;
isc_task_t * task;
isc_sockaddr_t address;
......@@ -91,18 +91,14 @@ struct controllistener {
ISC_LINK(controllistener_t) link;
};
static controllistenerlist_t listeners;
static isc_mutex_t listeners_lock;
static isc_once_t once = ISC_ONCE_INIT;
struct ns_controls {
ns_server_t *server;
controllistenerlist_t listeners;
};
static void control_newconn(isc_task_t *task, isc_event_t *event);
static void control_recvmessage(isc_task_t *task, isc_event_t *event);
static void
initialize_mutex(void) {
RUNTIME_CHECK(isc_mutex_init(&listeners_lock) == ISC_R_SUCCESS);
}
static void
free_controlkey(controlkey_t *key, isc_mem_t *mctx) {
if (key->keyname != NULL)
......@@ -494,22 +490,11 @@ control_newconn(isc_task_t *task, isc_event_t *event) {
}
void
ns_control_shutdown(isc_boolean_t exiting) {
ns_controls_shutdown(ns_controls_t *controls) {
controllistener_t *listener;
controllistener_t *next;
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
if (exiting) {
/*
* When not exiting, this function is called from
* ns_control_configure(), which already holds the lock.
*/
LOCK(&listeners_lock);
}
for (listener = ISC_LIST_HEAD(listeners);
for (listener = ISC_LIST_HEAD(controls->listeners);
listener != NULL;
listener = next)
{
......@@ -518,12 +503,9 @@ ns_control_shutdown(isc_boolean_t exiting) {
* call their callbacks.
*/
next = ISC_LIST_NEXT(listener, link);
ISC_LIST_UNLINK(listeners, listener, link);
ISC_LIST_UNLINK(controls->listeners, listener, link);
shutdown_listener(listener);
}
if (exiting)
UNLOCK(&listeners_lock);
}
static isc_result_t
......@@ -670,7 +652,8 @@ register_keys(cfg_obj_t *control, cfg_obj_t *keylist,
}
static void
update_listener(controllistener_t **listenerp, cfg_obj_t *control,
update_listener(ns_controls_t *cp,
controllistener_t **listenerp, cfg_obj_t *control,
cfg_obj_t *config, isc_sockaddr_t *addr,
ns_aclconfctx_t *aclconfctx, char *socktext)
{
......@@ -681,7 +664,7 @@ update_listener(controllistener_t **listenerp, cfg_obj_t *control,
controlkeylist_t keys;
isc_result_t result;
for (listener = ISC_LIST_HEAD(listeners);
for (listener = ISC_LIST_HEAD(cp->listeners);
listener != NULL;
listener = ISC_LIST_NEXT(listener, link))
if (isc_sockaddr_equal(addr, &listener->address))
......@@ -729,10 +712,11 @@ update_listener(controllistener_t **listenerp, cfg_obj_t *control,
}
static void
add_listener(isc_mem_t *mctx, controllistener_t **listenerp,
add_listener(ns_controls_t *cp, controllistener_t **listenerp,
cfg_obj_t *control, cfg_obj_t *config, isc_sockaddr_t *addr,
ns_aclconfctx_t *aclconfctx, char *socktext)
{
isc_mem_t *mctx = cp->server->mctx;
controllistener_t *listener;
cfg_obj_t *allow;
cfg_obj_t *keys;
......@@ -744,8 +728,9 @@ add_listener(isc_mem_t *mctx, controllistener_t **listenerp,
result = ISC_R_NOMEMORY;
if (result == ISC_R_SUCCESS) {
listener->controls = cp;
listener->mctx = mctx;
listener->task = ns_g_server->task;
listener->task = cp->server->task;
listener->address = *addr;
listener->sock = NULL;
listener->listening = ISC_FALSE;
......@@ -823,8 +808,9 @@ add_listener(isc_mem_t *mctx, controllistener_t **listenerp,
}
isc_result_t
ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx)
ns_controls_configure(ns_controls_t *cp,
cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx)
{
controllistener_t *listener;
controllistenerlist_t new_listeners;
......@@ -833,8 +819,6 @@ ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
cfg_listelt_t *element, *element2;
char socktext[ISC_SOCKADDR_FORMATSIZE];
RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);
ISC_LIST_INIT(new_listeners);
/*
......@@ -842,7 +826,6 @@ ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
*/
(void)cfg_map_get(config, "controls", &controlslist);
LOCK(&listeners_lock);
/*
* Run through the new control channel list, noting sockets that
* are already being listened on and moving them to the new list.
......@@ -930,7 +913,7 @@ ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
"processing control channel %s",
socktext);
update_listener(&listener, control, config,
update_listener(cp, &listener, control, config,
addr, aclconfctx, socktext);
if (listener != NULL)
......@@ -938,13 +921,14 @@ ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
* Remove the listener from the old
* list, so it won't be shut down.
*/
ISC_LIST_UNLINK(listeners, listener,
ISC_LIST_UNLINK(cp->listeners, listener,
link);
else
/*
* This is a new listener.
*/
add_listener(mctx, &listener, control,
add_listener(cp, &listener,
control,
config, addr, aclconfctx,
socktext);
......@@ -967,16 +951,36 @@ ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
* configuration (if any) that do not remain in the current
* configuration.
*/
ns_control_shutdown(ISC_FALSE);
ns_controls_shutdown(cp);
/*
* Put all of the valid listeners on the listeners list.
* Anything already on listeners in the process of shutting down
* will be taken care of by listen_done().
*/
ISC_LIST_APPENDLIST(listeners, new_listeners, link);
ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
UNLOCK(&listeners_lock);
return (ISC_R_SUCCESS);
}
isc_result_t
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp) {
isc_mem_t *mctx = server->mctx;
ns_controls_t *controls = isc_mem_get(mctx, sizeof(*controls));
if (controls == NULL)
return (ISC_R_NOMEMORY);
controls->server = server;
ISC_LIST_INIT(controls->listeners);
*ctrlsp = controls;
return (ISC_R_SUCCESS);
}
void
ns_controls_destroy(ns_controls_t **ctrlsp) {
ns_controls_t *controls = *ctrlsp;
REQUIRE(ISC_LIST_EMPTY(controls->listeners));
isc_mem_put(controls->server->mctx, controls, sizeof(*controls));
*ctrlsp = NULL;
}
......@@ -15,14 +15,19 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: control.h,v 1.4 2001/05/07 23:34:01 gson Exp $ */
/* $Id: control.h,v 1.5 2001/05/08 03:42:31 gson Exp $ */
#ifndef NAMED_CONTROL_H
#define NAMED_CONTROL_H 1
/*
* The name server command channel.
*/
#include <isccc/types.h>
#include <named/aclconf.h>
#include <named/types.h>
#define NS_CONTROL_PORT 953
......@@ -39,14 +44,35 @@
#define NS_COMMAND_FLUSH "flush"
isc_result_t
ns_control_init(void);
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
/*
* Create an initial, empty set of command channels for 'server'.
*/
void
ns_controls_destroy(ns_controls_t **ctrlsp);
/*
* Destroy a set of command channels.
*
* Requires:
* Shutdown of the channels has completed.
*/
isc_result_t
ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx);
ns_controls_configure(ns_controls_t *controls, cfg_obj_t *config,
ns_aclconfctx_t *aclconfctx);
/*
* Configure zero or more command channels into 'controls'
* as defined in the configuration parse tree 'config'.
* The channels will evaluate ACLs in the context of
* 'aclconfctx'.
*/
void
ns_control_shutdown(isc_boolean_t exiting);
ns_controls_shutdown(ns_controls_t *controls);
/*
* Initiate shutdown of all the command channels in 'controls'.
*/
isc_result_t
ns_control_docommand(isccc_sexpr_t *message);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.h,v 1.54 2001/05/07 23:34:02 gson Exp $ */
/* $Id: server.h,v 1.55 2001/05/08 03:42:33 gson Exp $ */
#ifndef NAMED_SERVER_H
#define NAMED_SERVER_H 1
......@@ -77,6 +77,8 @@ struct ns_server {
isc_uint64_t * querystats; /* Query statistics counters */
char * dumpfile; /* Dump file name */
ns_controls_t * controls; /* Control channels */
};
#define NS_SERVER_MAGIC 0x53564552 /* SVER */
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: types.h,v 1.18 2001/01/09 21:40:32 bwelling Exp $ */
/* $Id: types.h,v 1.19 2001/05/08 03:42:34 gson Exp $ */
#ifndef NAMED_TYPES_H
#define NAMED_TYPES_H 1
......@@ -34,5 +34,6 @@ typedef struct ns_lwdclient ns_lwdclient_t;
typedef struct ns_lwdclientmgr ns_lwdclientmgr_t;
typedef struct ns_lwsearchlist ns_lwsearchlist_t;
typedef struct ns_lwsearchctx ns_lwsearchctx_t;
typedef struct ns_controls ns_controls_t;
#endif /* NAMED_TYPES_H */
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: main.c,v 1.107 2001/03/29 04:23:51 gson Exp $ */
/* $Id: main.c,v 1.108 2001/05/08 03:42:28 gson Exp $ */
#include <config.h>
......@@ -419,13 +419,6 @@ create_managers(void) {
static void
destroy_managers(void) {
if (!ns_g_lwresdonly)
/*
* The command channel listeners need to be stopped here so
* that isc_taskmgr_destroy() won't block on the server task.
*/
ns_control_shutdown(ISC_TRUE);
ns_lwresd_shutdown();
isc_entropy_detach(&ns_g_entropy);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.320 2001/05/08 00:26:24 gson Exp $ */
/* $Id: server.c,v 1.321 2001/05/08 03:42:30 gson Exp $ */
#include <config.h>
......@@ -1863,7 +1863,8 @@ load_configuration(const char *filename, ns_server_t *server,
/*
* Bind the control port(s).
*/
CHECKM(ns_control_configure(ns_g_mctx, config, &aclconfctx),
CHECKM(ns_controls_configure(ns_g_server->controls, config,
&aclconfctx),
"binding control channel(s)");
/*
......@@ -2160,6 +2161,8 @@ shutdown_server(isc_task_t *task, isc_event_t *event) {
ISC_LOG_INFO, "shutting down%s",
flush ? ": flushing changes" : "");
ns_controls_shutdown(server->controls);
cfg_obj_destroy(ns_g_parser, &ns_g_config);
cfg_parser_destroy(&ns_g_parser);
......@@ -2284,6 +2287,10 @@ ns_server_create(isc_mem_t *mctx, ns_server_t **serverp) {
server->flushonshutdown = ISC_FALSE;
server->log_queries = ISC_FALSE;
server->controls = NULL;
CHECKFATAL(ns_controls_create(server, &server->controls),
"ns_controls_create");
server->magic = NS_SERVER_MAGIC;
*serverp = server;
}
......@@ -2293,6 +2300,8 @@ ns_server_destroy(ns_server_t **serverp) {
ns_server_t *server = *serverp;
REQUIRE(NS_SERVER_VALID(server));
ns_controls_destroy(&server->controls);
dns_stats_freecounters(server->mctx, &server->querystats);
isc_mem_free(server->mctx, server->statsfile);
......
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