mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 01:59:59 -04:00
initate command channel shutdown from the server task, not the
main task, to avoid race conditions; eliminate global variables in controlconf.c
This commit is contained in:
parent
bdfb3735ac
commit
532989b206
6 changed files with 97 additions and 62 deletions
|
|
@ -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);
|
||||
|
||||
UNLOCK(&listeners_lock);
|
||||
ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link);
|
||||
|
||||
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);
|
||||
|
||||
isc_result_t
|
||||
ns_control_configure(isc_mem_t *mctx, cfg_obj_t *config,
|
||||
ns_aclconfctx_t *aclconfctx);
|
||||
ns_controls_create(ns_server_t *server, ns_controls_t **ctrlsp);
|
||||
/*
|
||||
* Create an initial, empty set of command channels for 'server'.
|
||||
*/
|
||||
|
||||
void
|
||||
ns_control_shutdown(isc_boolean_t exiting);
|
||||
ns_controls_destroy(ns_controls_t **ctrlsp);
|
||||
/*
|
||||
* Destroy a set of command channels.
|
||||
*
|
||||
* Requires:
|
||||
* Shutdown of the channels has completed.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
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_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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue