diff --git a/bin/delv/delv.c b/bin/delv/delv.c index c9399c1e21..7cab8602ea 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -1622,9 +1622,9 @@ main(int argc, char *argv[]) { fatal("failed to create mctx"); CHECK(isc_appctx_create(mctx, &actx)); - CHECK(isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr)); - CHECK(isc_socketmgr_createinctx(mctx, actx, &socketmgr)); - CHECK(isc_timermgr_createinctx(mctx, actx, &timermgr)); + CHECK(isc_taskmgr_createinctx(mctx, 1, 0, &taskmgr)); + CHECK(isc_socketmgr_createinctx(mctx, &socketmgr)); + CHECK(isc_timermgr_createinctx(mctx, &timermgr)); parse_args(argc, argv); diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 05a7ca222b..4c174364ed 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -278,7 +278,7 @@ rndc_senddone(isc_task_t *task, isc_event_t *event) { if (sends == 0 && recvs == 0) { isc_socket_detach(&sock); isc_task_shutdown(task); - RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS); + isc_app_shutdown(); } } @@ -347,7 +347,7 @@ rndc_recvdone(isc_task_t *task, isc_event_t *event) { if (sends == 0 && recvs == 0) { isc_socket_detach(&sock); isc_task_shutdown(task); - RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS); + isc_app_shutdown(); } } diff --git a/bin/tests/optional/shutdown_test.c b/bin/tests/optional/shutdown_test.c index f11b799763..42b898c505 100644 --- a/bin/tests/optional/shutdown_test.c +++ b/bin/tests/optional/shutdown_test.c @@ -98,7 +98,7 @@ tick(isc_task_t *task, isc_event_t *event) { info->ticks++; if (strcmp(info->name, "1") == 0) { if (info->ticks == 10) { - RUNTIME_CHECK(isc_app_shutdown() == ISC_R_SUCCESS); + isc_app_shutdown(); } else if (info->ticks >= 15 && info->exiting) { isc_timer_detach(&info->timer); isc_task_detach(&info->task); diff --git a/configure.ac b/configure.ac index c249f44e12..83ff9bfda9 100644 --- a/configure.ac +++ b/configure.ac @@ -635,10 +635,7 @@ LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" -# -# We'd like to use sigwait() too -# -AC_CHECK_FUNCS([sigwait pthread_attr_getstacksize pthread_attr_setstacksize]) +AC_CHECK_FUNCS([pthread_attr_getstacksize pthread_attr_setstacksize]) AC_ARG_WITH([locktype], AS_HELP_STRING([--with-locktype=ARG], diff --git a/lib/dns/client.c b/lib/dns/client.c index de70ff15ba..c7866dc7c5 100644 --- a/lib/dns/client.c +++ b/lib/dns/client.c @@ -420,13 +420,13 @@ dns_client_create(dns_client_t **clientp, unsigned int options) { result = isc_app_ctxstart(actx); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr); + result = isc_taskmgr_createinctx(mctx, 1, 0, &taskmgr); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_socketmgr_createinctx(mctx, actx, &socketmgr); + result = isc_socketmgr_createinctx(mctx, &socketmgr); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_timermgr_createinctx(mctx, actx, &timermgr); + result = isc_timermgr_createinctx(mctx, &timermgr); if (result != ISC_R_SUCCESS) goto cleanup; #if 0 diff --git a/lib/irs/context.c b/lib/irs/context.c index 2c96614394..8057fe3551 100644 --- a/lib/irs/context.c +++ b/lib/irs/context.c @@ -101,15 +101,15 @@ ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, if (result != ISC_R_SUCCESS) goto fail; - result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + result = isc_taskmgr_createinctx(*mctxp, 1, 0, taskmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + result = isc_socketmgr_createinctx(*mctxp, socketmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + result = isc_timermgr_createinctx(*mctxp, timermgrp); if (result != ISC_R_SUCCESS) goto fail; diff --git a/lib/isc/include/isc/app.h b/lib/isc/include/isc/app.h index 75161b9fe3..4ee550a687 100644 --- a/lib/isc/include/isc/app.h +++ b/lib/isc/include/isc/app.h @@ -103,14 +103,7 @@ typedef isc_event_t isc_appevent_t; * of the isc_app_ routines to work. app implementations must maintain * all app context invariants. */ -struct isc_appctx { - unsigned int impmagic; - unsigned int magic; -}; - -#define ISCAPI_APPCTX_MAGIC ISC_MAGIC('A','a','p','c') -#define ISCAPI_APPCTX_VALID(c) ((c) != NULL && \ - (c)->magic == ISCAPI_APPCTX_MAGIC) +struct isc_appctx; ISC_LANG_BEGINDECLS @@ -184,10 +177,10 @@ isc_app_isrunning(void); *\li false App is not running. */ -isc_result_t +void isc_app_ctxshutdown(isc_appctx_t *ctx); -isc_result_t +void isc_app_shutdown(void); /*!< * \brief Request application shutdown. @@ -205,13 +198,13 @@ isc_app_shutdown(void); *\li ISC_R_UNEXPECTED */ -isc_result_t +void isc_app_ctxsuspend(isc_appctx_t *ctx); /*!< * \brief This has the same behavior as isc_app_ctxsuspend(). */ -isc_result_t +void isc_app_reload(void); /*!< * \brief Request application reload. @@ -295,44 +288,6 @@ isc_appctx_destroy(isc_appctx_t **ctxp); *\li *ctxp == NULL. */ -void -isc_appctx_settaskmgr(isc_appctx_t *ctx, isc_taskmgr_t *taskmgr); -/*!< - * \brief Associate a task manager with an application context. - * - * This must be done before running tasks within the application context. - * - * Requires: - *\li 'ctx' is a valid application context. - *\li 'taskmgr' is a valid task manager. - */ - -void -isc_appctx_setsocketmgr(isc_appctx_t *ctx, isc_socketmgr_t *socketmgr); -/*!< - * \brief Associate a socket manager with an application context. - * - * This must be done before handling socket events within the application - * context. - * - * Requires: - *\li 'ctx' is a valid application context. - *\li 'socketmgr' is a valid socket manager. - */ - -void -isc_appctx_settimermgr(isc_appctx_t *ctx, isc_timermgr_t *timermgr); -/*!< - * \brief Associate a socket timer with an application context. - * - * This must be done before handling timer events within the application - * context. - * - * Requires: - *\li 'ctx' is a valid application context. - *\li 'timermgr' is a valid timer manager. - */ - ISC_LANG_ENDDECLS #endif /* ISC_APP_H */ diff --git a/lib/isc/include/isc/socket.h b/lib/isc/include/isc/socket.h index 98fa51bfd6..22cf7bf568 100644 --- a/lib/isc/include/isc/socket.h +++ b/lib/isc/include/isc/socket.h @@ -805,8 +805,7 @@ isc_socket_sendto2(isc_socket_t *sock, isc_region_t *region, /*@}*/ isc_result_t -isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, - isc_socketmgr_t **managerp); +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_socketmgr_t **managerp); isc_result_t isc_socketmgr_create(isc_mem_t *mctx, isc_socketmgr_t **managerp); diff --git a/lib/isc/include/isc/task.h b/lib/isc/include/isc/task.h index b2d9c48384..f9752f01bb 100644 --- a/lib/isc/include/isc/task.h +++ b/lib/isc/include/isc/task.h @@ -630,7 +630,7 @@ isc_task_privilege(isc_task_t *task); *****/ isc_result_t -isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, +isc_taskmgr_createinctx(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp); isc_result_t diff --git a/lib/isc/include/isc/timer.h b/lib/isc/include/isc/timer.h index c8f31d9d14..53aeaa50bf 100644 --- a/lib/isc/include/isc/timer.h +++ b/lib/isc/include/isc/timer.h @@ -316,8 +316,7 @@ isc_timer_gettype(isc_timer_t *timer); */ isc_result_t -isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, - isc_timermgr_t **managerp); +isc_timermgr_createinctx(isc_mem_t *mctx, isc_timermgr_t **managerp); isc_result_t isc_timermgr_create(isc_mem_t *mctx, isc_timermgr_t **managerp); diff --git a/lib/isc/task.c b/lib/isc/task.c index c75b99624f..fff7e10b9d 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -1871,7 +1871,7 @@ isc_taskmgr_renderjson(isc_taskmgr_t *mgr0, json_object *tasks) { isc_result_t -isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, +isc_taskmgr_createinctx(isc_mem_t *mctx, unsigned int workers, unsigned int default_quantum, isc_taskmgr_t **managerp) { @@ -1880,8 +1880,5 @@ isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, result = isc_taskmgr_create(mctx, workers, default_quantum, managerp); - if (result == ISC_R_SUCCESS) - isc_appctx_settaskmgr(actx, *managerp); - return (result); } diff --git a/lib/isc/timer.c b/lib/isc/timer.c index fee0813d81..729fcb5608 100644 --- a/lib/isc/timer.c +++ b/lib/isc/timer.c @@ -784,15 +784,11 @@ isc_timermgr_destroy(isc_timermgr_t **managerp) { } isc_result_t -isc_timermgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, - isc_timermgr_t **managerp) +isc_timermgr_createinctx(isc_mem_t *mctx, isc_timermgr_t **managerp) { isc_result_t result; result = isc_timermgr_create(mctx, managerp); - if (result == ISC_R_SUCCESS) - isc_appctx_settimermgr(actx, *managerp); - return (result); } diff --git a/lib/isc/unix/app.c b/lib/isc/unix/app.c index 56434a564c..a65121b717 100644 --- a/lib/isc/unix/app.c +++ b/lib/isc/unix/app.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include #include @@ -48,7 +49,7 @@ * as an event loop dispatching various events. */ static pthread_t blockedthread; -static bool is_running; +static atomic_bool is_running; /* * The application context of this module. This implementation actually @@ -57,72 +58,41 @@ static bool is_running; #define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x') #define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC) -typedef struct isc__appctx { - isc_appctx_t common; +struct isc_appctx { + unsigned int magic; isc_mem_t *mctx; isc_mutex_t lock; - isc_eventlist_t on_run; - bool shutdown_requested; - bool running; - - /*! - * We assume that 'want_shutdown' can be read and written atomically. - */ - bool want_shutdown; - /* - * We assume that 'want_reload' can be read and written atomically. - */ - bool want_reload; - - bool blocked; - - isc_taskmgr_t *taskmgr; - isc_socketmgr_t *socketmgr; - isc_timermgr_t *timermgr; + isc_eventlist_t on_run; + atomic_bool shutdown_requested; + atomic_bool running; + atomic_bool want_shutdown; + atomic_bool want_reload; + atomic_bool blocked; isc_mutex_t readylock; - isc_condition_t ready; -} isc__appctx_t; + isc_condition_t ready; +}; -static isc__appctx_t isc_g_appctx; - -#ifndef HAVE_SIGWAIT -static void -exit_action(int arg) { - UNUSED(arg); - isc_g_appctx.want_shutdown = true; -} +static isc_appctx_t isc_g_appctx; static void -reload_action(int arg) { - UNUSED(arg); - isc_g_appctx.want_reload = true; -} -#endif - -static isc_result_t handle_signal(int sig, void (*handler)(int)) { struct sigaction sa; - char strbuf[ISC_STRERRORSIZE]; memset(&sa, 0, sizeof(sa)); sa.sa_handler = handler; if (sigfillset(&sa.sa_mask) != 0 || sigaction(sig, &sa, NULL) < 0) { + char strbuf[ISC_STRERRORSIZE]; strerror_r(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_error_fatal(__FILE__, __LINE__, "handle_signal() %d setup: %s", sig, strbuf); - return (ISC_R_UNEXPECTED); } - - return (ISC_R_SUCCESS); } isc_result_t -isc_app_ctxstart(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - isc_result_t result; +isc_app_ctxstart(isc_appctx_t *ctx) { int presult; sigset_t sset; char strbuf[ISC_STRERRORSIZE]; @@ -133,64 +103,27 @@ isc_app_ctxstart(isc_appctx_t *ctx0) { * Start an ISC library application. */ - isc_mutex_init(&ctx->readylock); - - isc_condition_init(&ctx->ready); - isc_mutex_init(&ctx->lock); + isc_mutex_init(&ctx->readylock); + isc_condition_init(&ctx->ready); + ISC_LIST_INIT(ctx->on_run); - ctx->shutdown_requested = false; - ctx->running = false; - ctx->want_shutdown = false; - ctx->want_reload = false; - ctx->blocked = false; - -#ifndef HAVE_SIGWAIT - /* - * Install do-nothing handlers for SIGINT and SIGTERM. - * - * We install them now because BSDI 3.1 won't block - * the default actions, regardless of what we do with - * pthread_sigmask(). - */ - result = handle_signal(SIGINT, exit_action); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = handle_signal(SIGTERM, exit_action); - if (result != ISC_R_SUCCESS) - goto cleanup; -#endif + atomic_init(&ctx->shutdown_requested, false); + atomic_init(&ctx->running, false); + atomic_init(&ctx->want_shutdown, false); + atomic_init(&ctx->want_reload, false); + atomic_init(&ctx->blocked, false); /* * Always ignore SIGPIPE. */ - result = handle_signal(SIGPIPE, SIG_IGN); - if (result != ISC_R_SUCCESS) - goto cleanup; + handle_signal(SIGPIPE, SIG_IGN); - /* - * On Solaris 2, delivery of a signal whose action is SIG_IGN - * will not cause sigwait() to return. We may have inherited - * unexpected actions for SIGHUP, SIGINT, and SIGTERM from our parent - * process (e.g, Solaris cron). Set an action of SIG_DFL to make - * sure sigwait() works as expected. Only do this for SIGTERM and - * SIGINT if we don't have sigwait(), since a different handler is - * installed above. - */ - result = handle_signal(SIGHUP, SIG_DFL); - if (result != ISC_R_SUCCESS) - goto cleanup; - -#ifdef HAVE_SIGWAIT - result = handle_signal(SIGTERM, SIG_DFL); - if (result != ISC_R_SUCCESS) - goto cleanup; - result = handle_signal(SIGINT, SIG_DFL); - if (result != ISC_R_SUCCESS) - goto cleanup; -#endif + handle_signal(SIGHUP, SIG_DFL); + handle_signal(SIGTERM, SIG_DFL); + handle_signal(SIGINT, SIG_DFL); /* * Block SIGHUP, SIGINT, SIGTERM. @@ -206,61 +139,45 @@ isc_app_ctxstart(isc_appctx_t *ctx0) { sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { strerror_r(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_error_fatal(__FILE__, __LINE__, "isc_app_start() sigsetops: %s", strbuf); - result = ISC_R_UNEXPECTED; - goto cleanup; } presult = pthread_sigmask(SIG_BLOCK, &sset, NULL); if (presult != 0) { strerror_r(presult, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, + isc_error_fatal(__FILE__, __LINE__, "isc_app_start() pthread_sigmask: %s", strbuf); - result = ISC_R_UNEXPECTED; - goto cleanup; } return (ISC_R_SUCCESS); - - cleanup: - (void)isc_condition_destroy(&ctx->ready); - (void)isc_mutex_destroy(&ctx->readylock); - return (result); } isc_result_t isc_app_start(void) { - isc_g_appctx.common.impmagic = APPCTX_MAGIC; - isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; + isc_g_appctx.magic = APPCTX_MAGIC; isc_g_appctx.mctx = NULL; /* The remaining members will be initialized in ctxstart() */ - return (isc_app_ctxstart((isc_appctx_t *)&isc_g_appctx)); + return (isc_app_ctxstart(&isc_g_appctx)); } isc_result_t isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { - return (isc_app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx, - task, action, arg)); + return (isc_app_ctxonrun(&isc_g_appctx, mctx, task, action, arg)); } isc_result_t -isc_app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, +isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_event_t *event; isc_task_t *cloned_task = NULL; - isc_result_t result; - LOCK(&ctx->lock); - - if (ctx->running) { - result = ISC_R_ALREADYRUNNING; - goto unlock; + if (atomic_load_acquire(&ctx->running)) { + return (ISC_R_ALREADYRUNNING); } /* @@ -272,42 +189,34 @@ isc_app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, action, arg, sizeof(*event)); if (event == NULL) { isc_task_detach(&cloned_task); - result = ISC_R_NOMEMORY; - goto unlock; + return (ISC_R_NOMEMORY); } + LOCK(&ctx->lock); ISC_LIST_APPEND(ctx->on_run, event, ev_link); - - result = ISC_R_SUCCESS; - - unlock: UNLOCK(&ctx->lock); - return (result); + return (ISC_R_SUCCESS); } isc_result_t -isc_app_ctxrun(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - int result; +isc_app_ctxrun(isc_appctx_t *ctx) { isc_event_t *event, *next_event; isc_task_t *task; sigset_t sset; - char strbuf[ISC_STRERRORSIZE]; -#ifdef HAVE_SIGWAIT int sig; -#endif /* HAVE_SIGWAIT */ + bool exp_false = false; + bool exp_true = true; REQUIRE(VALID_APPCTX(ctx)); - LOCK(&ctx->lock); - - if (!ctx->running) { - ctx->running = true; - + if (atomic_compare_exchange_weak_acq_rel( + &ctx->running, &exp_false, true) == true) + { /* * Post any on-run events (in FIFO order). */ + LOCK(&ctx->lock); for (event = ISC_LIST_HEAD(ctx->on_run); event != NULL; event = next_event) { @@ -317,17 +226,15 @@ isc_app_ctxrun(isc_appctx_t *ctx0) { event->ev_sender = NULL; isc_task_sendanddetach(&task, &event); } - + UNLOCK(&ctx->lock); } - UNLOCK(&ctx->lock); - /* * BIND9 internal tools using multiple contexts do not - * rely on signal. - */ - if (isc_bind9 && ctx != &isc_g_appctx) + * rely on signal. */ + if (isc_bind9 && ctx != &isc_g_appctx) { return (ISC_R_SUCCESS); + } /* * There is no danger if isc_app_shutdown() is called before we @@ -335,8 +242,7 @@ isc_app_ctxrun(isc_appctx_t *ctx0) { * simply be made pending and we will get it when we call * sigwait(). */ - while (!ctx->want_shutdown) { -#ifdef HAVE_SIGWAIT + while (atomic_load_acquire(&ctx->want_shutdown) == false) { if (isc_bind9) { /* * BIND9 internal; single context: @@ -346,88 +252,56 @@ isc_app_ctxrun(isc_appctx_t *ctx0) { sigaddset(&sset, SIGHUP) != 0 || sigaddset(&sset, SIGINT) != 0 || sigaddset(&sset, SIGTERM) != 0) { + char strbuf[ISC_STRERRORSIZE]; strerror_r(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", - strbuf); - return (ISC_R_UNEXPECTED); + isc_error_fatal(__FILE__, __LINE__, + "isc_app_run() sigsetops: %s", + strbuf); } - result = sigwait(&sset, &sig); - if (result == 0) { - if (sig == SIGINT || sig == SIGTERM) - ctx->want_shutdown = true; - else if (sig == SIGHUP) - ctx->want_reload = true; + if (sigwait(&sset, &sig) == 0) { + switch (sig) { + case SIGINT: + case SIGTERM: + atomic_store_release( + &ctx->want_shutdown, true); + break; + case SIGHUP: + atomic_store_release( + &ctx->want_reload, true); + break; + default: + INSIST(0); + ISC_UNREACHABLE(); + } } - } else { /* * External, or BIND9 using multiple contexts: * wait until woken up. */ - LOCK(&ctx->readylock); - if (ctx->want_shutdown) { - /* shutdown() won the race. */ - UNLOCK(&ctx->readylock); + if (atomic_load_acquire(&ctx->want_shutdown)) { break; } - if (!ctx->want_reload) + if (!atomic_load_acquire(&ctx->want_reload)) { + LOCK(&ctx->readylock); WAIT(&ctx->ready, &ctx->readylock); - UNLOCK(&ctx->readylock); - } -#else /* Don't have sigwait(). */ - if (isc_bind9) { - /* - * BIND9 internal; single context: - * Install a signal handler for SIGHUP, then wait for - * all signals. - */ - result = handle_signal(SIGHUP, reload_action); - if (result != ISC_R_SUCCESS) - return (ISC_R_SUCCESS); - - if (sigemptyset(&sset) != 0) { - strerror_r(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } -#ifdef HAVE_GPERFTOOLS_PROFILER - if (sigaddset(&sset, SIGALRM) != 0) { - strerror_r(errno, strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_run() sigsetops: %s", - strbuf); - return (ISC_R_UNEXPECTED); - } -#endif - (void)sigsuspend(&sset); - } else { - /* - * External, or BIND9 using multiple contexts: - * wait until woken up. - */ - LOCK(&ctx->readylock); - if (ctx->want_shutdown) { - /* shutdown() won the race. */ UNLOCK(&ctx->readylock); - break; } - if (!ctx->want_reload) - WAIT(&ctx->ready, &ctx->readylock); - UNLOCK(&ctx->readylock); } -#endif /* HAVE_SIGWAIT */ - if (ctx->want_reload) { - ctx->want_reload = false; + exp_true = true; + if (atomic_compare_exchange_weak_acq_rel(&ctx->want_reload, + &exp_true, + false)) + { return (ISC_R_RELOAD); } - if (ctx->want_shutdown && ctx->blocked) + if (atomic_load_acquire(&ctx->want_shutdown) && + atomic_load_acquire(&ctx->blocked)) { exit(1); + } } return (ISC_R_SUCCESS); @@ -436,139 +310,113 @@ isc_app_ctxrun(isc_appctx_t *ctx0) { isc_result_t isc_app_run(void) { isc_result_t result; + bool exp_false = false; - is_running = true; - result = isc_app_ctxrun((isc_appctx_t *)&isc_g_appctx); - is_running = false; + REQUIRE(atomic_compare_exchange_weak_acq_rel( + &is_running, &exp_false, true) == true); + result = isc_app_ctxrun(&isc_g_appctx); + atomic_store_release(&is_running, false); return (result); } bool isc_app_isrunning() { - return (is_running); + return (atomic_load_acquire(&is_running)); } -isc_result_t -isc_app_ctxshutdown(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - bool want_kill = true; - char strbuf[ISC_STRERRORSIZE]; +void +isc_app_ctxshutdown(isc_appctx_t *ctx) { + bool exp_false = false; REQUIRE(VALID_APPCTX(ctx)); - LOCK(&ctx->lock); + REQUIRE(atomic_load_acquire(&ctx->running)); - REQUIRE(ctx->running); - - if (ctx->shutdown_requested) - want_kill = false; - else - ctx->shutdown_requested = true; - - UNLOCK(&ctx->lock); - - if (want_kill) { - if (isc_bind9 && ctx != &isc_g_appctx) + /* If ctx->shutdown_requested == true, we are already shutting + * down and we want to just bail out. + */ + if (atomic_compare_exchange_weak_acq_rel( + &ctx->shutdown_requested, + &exp_false, + true)) + { + if (isc_bind9 && ctx != &isc_g_appctx) { /* BIND9 internal, but using multiple contexts */ - ctx->want_shutdown = true; - else { - if (isc_bind9) { - /* BIND9 internal, single context */ - if (kill(getpid(), SIGTERM) < 0) { - strerror_r(errno, - strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_shutdown() " - "kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } - } - else { - /* External, multiple contexts */ - LOCK(&ctx->readylock); - ctx->want_shutdown = true; - UNLOCK(&ctx->readylock); - SIGNAL(&ctx->ready); + atomic_store_release(&ctx->want_shutdown, true); + } else if (isc_bind9) { + /* BIND9 internal, single context */ + if (kill(getpid(), SIGTERM) < 0) { + char strbuf[ISC_STRERRORSIZE]; + strerror_r(errno, + strbuf, sizeof(strbuf)); + isc_error_fatal(__FILE__, __LINE__, + "isc_app_shutdown() " + "kill: %s", strbuf); } + } else { + /* External, multiple contexts */ + atomic_store_release(&ctx->want_shutdown, true); + SIGNAL(&ctx->ready); } } - return (ISC_R_SUCCESS); } -isc_result_t +void isc_app_shutdown(void) { - return (isc_app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); + isc_app_ctxshutdown(&isc_g_appctx); } -isc_result_t -isc_app_ctxsuspend(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - bool want_kill = true; - char strbuf[ISC_STRERRORSIZE]; - +void +isc_app_ctxsuspend(isc_appctx_t *ctx) { REQUIRE(VALID_APPCTX(ctx)); - LOCK(&ctx->lock); - - REQUIRE(ctx->running); + REQUIRE(atomic_load(&ctx->running)); /* * Don't send the reload signal if we're shutting down. */ - if (ctx->shutdown_requested) - want_kill = false; - - UNLOCK(&ctx->lock); - - if (want_kill) { - if (isc_bind9 && ctx != &isc_g_appctx) + if (atomic_load_acquire(&ctx->shutdown_requested) == false) { + if (isc_bind9 && ctx != &isc_g_appctx) { /* BIND9 internal, but using multiple contexts */ - ctx->want_reload = true; - else { - ctx->want_reload = true; - if (isc_bind9) { - /* BIND9 internal, single context */ - if (kill(getpid(), SIGHUP) < 0) { - strerror_r(errno, - strbuf, sizeof(strbuf)); - UNEXPECTED_ERROR(__FILE__, __LINE__, - "isc_app_reload() " - "kill: %s", strbuf); - return (ISC_R_UNEXPECTED); - } - } - else { - /* External, multiple contexts */ - LOCK(&ctx->readylock); - ctx->want_reload = true; - UNLOCK(&ctx->readylock); - SIGNAL(&ctx->ready); + atomic_store_release(&ctx->want_reload, true); + } else if (isc_bind9) { + /* BIND9 internal, single context */ + if (kill(getpid(), SIGHUP) < 0) { + char strbuf[ISC_STRERRORSIZE]; + strerror_r(errno, + strbuf, sizeof(strbuf)); + isc_error_fatal(__FILE__, __LINE__, + "isc_app_reload() " + "kill: %s", strbuf); } + } else { + /* External, multiple contexts */ + atomic_store_release(&ctx->want_reload, true); + SIGNAL(&ctx->ready); } + } - - return (ISC_R_SUCCESS); -} - -isc_result_t -isc_app_reload(void) { - return (isc_app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); } void -isc_app_ctxfinish(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; +isc_app_reload(void) { + return (isc_app_ctxsuspend(&isc_g_appctx)); +} +void +isc_app_ctxfinish(isc_appctx_t *ctx) { REQUIRE(VALID_APPCTX(ctx)); isc_mutex_destroy(&ctx->lock); + isc_mutex_destroy(&ctx->readylock); + isc_condition_destroy(&ctx->ready); } void isc_app_finish(void) { - isc_app_ctxfinish((isc_appctx_t *)&isc_g_appctx); + isc_app_ctxfinish(&isc_g_appctx); } void @@ -577,7 +425,7 @@ isc_app_block(void) { REQUIRE(isc_g_appctx.running); REQUIRE(!isc_g_appctx.blocked); - isc_g_appctx.blocked = true; + atomic_store_release(&isc_g_appctx.blocked, true); blockedthread = pthread_self(); RUNTIME_CHECK(sigemptyset(&sset) == 0 && sigaddset(&sset, SIGINT) == 0 && @@ -588,11 +436,13 @@ isc_app_block(void) { void isc_app_unblock(void) { sigset_t sset; + bool exp_true = true; - REQUIRE(isc_g_appctx.running); - REQUIRE(isc_g_appctx.blocked); - - isc_g_appctx.blocked = false; + REQUIRE(atomic_load_acquire(&isc_g_appctx.running)); + REQUIRE(atomic_compare_exchange_weak_acq_rel( + &isc_g_appctx.blocked, + &exp_true, + false)); REQUIRE(blockedthread == pthread_self()); @@ -604,7 +454,7 @@ isc_app_unblock(void) { isc_result_t isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { - isc__appctx_t *ctx; + isc_appctx_t *ctx; REQUIRE(mctx != NULL); REQUIRE(ctxp != NULL && *ctxp == NULL); @@ -613,57 +463,26 @@ isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { if (ctx == NULL) return (ISC_R_NOMEMORY); - ctx->common.impmagic = APPCTX_MAGIC; - ctx->common.magic = ISCAPI_APPCTX_MAGIC; + ctx->magic = APPCTX_MAGIC; ctx->mctx = NULL; isc_mem_attach(mctx, &ctx->mctx); - ctx->taskmgr = NULL; - ctx->socketmgr = NULL; - ctx->timermgr = NULL; - - *ctxp = (isc_appctx_t *)ctx; + *ctxp = ctx; return (ISC_R_SUCCESS); } void isc_appctx_destroy(isc_appctx_t **ctxp) { - isc__appctx_t *ctx; + isc_appctx_t *ctx; REQUIRE(ctxp != NULL); - ctx = (isc__appctx_t *)*ctxp; + ctx = *ctxp; REQUIRE(VALID_APPCTX(ctx)); + *ctxp = NULL; + + ctx->magic = 0; isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx)); - - *ctxp = NULL; -} - -void -isc_appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->taskmgr = taskmgr; -} - -void -isc_appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->socketmgr = socketmgr; -} - -void -isc_appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->timermgr = timermgr; } diff --git a/lib/isc/unix/socket.c b/lib/isc/unix/socket.c index 58fa29e3db..d62af359d5 100644 --- a/lib/isc/unix/socket.c +++ b/lib/isc/unix/socket.c @@ -5608,15 +5608,11 @@ isc_socketmgr_renderjson(isc_socketmgr_t *mgr0, json_object *stats) { #endif /* HAVE_JSON */ isc_result_t -isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, - isc_socketmgr_t **managerp) +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_socketmgr_t **managerp) { isc_result_t result; result = isc_socketmgr_create(mctx, managerp); - if (result == ISC_R_SUCCESS) - isc_appctx_setsocketmgr(actx, *managerp); - return (result); } diff --git a/lib/isc/win32/app.c b/lib/isc/win32/app.c index 95fa112942..5adef3106b 100644 --- a/lib/isc/win32/app.c +++ b/lib/isc/win32/app.c @@ -50,7 +50,7 @@ enum { SHUTDOWN_EVENT }; -typedef struct isc__appctx { +struct isc_appctx { isc_appctx_t common; isc_mem_t *mctx; isc_eventlist_t on_run; @@ -69,13 +69,9 @@ typedef struct isc__appctx { bool blocked; HANDLE hEvents[NUM_EVENTS]; +}; - isc_taskmgr_t *taskmgr; - isc_socketmgr_t *socketmgr; - isc_timermgr_t *timermgr; -} isc__appctx_t; - -static isc__appctx_t isc_g_appctx; +static isc_appctx_t isc_g_appctx; /* * We need to remember which thread is the main thread... @@ -83,8 +79,7 @@ static isc__appctx_t isc_g_appctx; static isc_thread_t main_thread; isc_result_t -isc_app_ctxstart(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; +isc_app_ctxstart(isc_appctx_t *ctx) { isc_result_t result; REQUIRE(VALID_APPCTX(ctx)); @@ -115,27 +110,24 @@ isc_app_ctxstart(isc_appctx_t *ctx0) { isc_result_t isc_app_start(void) { - isc_g_appctx.common.impmagic = APPCTX_MAGIC; - isc_g_appctx.common.magic = ISCAPI_APPCTX_MAGIC; + isc_g_appctx.magic = APPCTX_MAGIC; isc_g_appctx.mctx = NULL; /* The remaining members will be initialized in ctxstart() */ - return (isc_app_ctxstart((isc_appctx_t *)&isc_g_appctx)); + return (isc_app_ctxstart(&isc_g_appctx)); } isc_result_t isc_app_onrun(isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { - return (isc_app_ctxonrun((isc_appctx_t *)&isc_g_appctx, mctx, - task, action, arg)); + return (isc_app_ctxonrun(&isc_g_appctx, mctx, task, action, arg)); } isc_result_t -isc_app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, +isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task, isc_taskaction_t action, void *arg) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; isc_event_t *event; isc_task_t *cloned_task = NULL; isc_result_t result; @@ -171,8 +163,7 @@ isc_app_ctxonrun(isc_appctx_t *ctx0, isc_mem_t *mctx, isc_task_t *task, } isc_result_t -isc_app_ctxrun(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; +isc_app_ctxrun(isc_appctx_t *ctx) { isc_event_t *event, *next_event; isc_task_t *task; HANDLE *pHandles = NULL; @@ -248,7 +239,7 @@ isc_app_run(void) { isc_result_t result; is_running = true; - result = isc_app_ctxrun((isc_appctx_t *)&isc_g_appctx); + result = isc_app_ctxrun(&isc_g_appctx); is_running = false; return (result); @@ -260,8 +251,7 @@ isc_app_isrunning() { } isc_result_t -isc_app_ctxshutdown(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; +isc_app_ctxshutdown(isc_appctx_t *ctx) { bool want_kill = true; REQUIRE(VALID_APPCTX(ctx)); @@ -285,12 +275,11 @@ isc_app_ctxshutdown(isc_appctx_t *ctx0) { isc_result_t isc_app_shutdown(void) { - return (isc_app_ctxshutdown((isc_appctx_t *)&isc_g_appctx)); + return (isc_app_ctxshutdown(&isc_g_appctx)); } isc_result_t -isc_app_ctxsuspend(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; +isc_app_ctxsuspend(isc_appctx_t *ctx) { bool want_kill = true; REQUIRE(VALID_APPCTX(ctx)); @@ -315,13 +304,11 @@ isc_app_ctxsuspend(isc_appctx_t *ctx0) { isc_result_t isc_app_reload(void) { - return (isc_app_ctxsuspend((isc_appctx_t *)&isc_g_appctx)); + return (isc_app_ctxsuspend(&isc_g_appctx)); } void -isc_app_ctxfinish(isc_appctx_t *ctx0) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - +isc_app_ctxfinish(isc_appctx_t *ctx) { REQUIRE(VALID_APPCTX(ctx)); isc_mutex_destroy(&ctx->lock); @@ -329,7 +316,7 @@ isc_app_ctxfinish(isc_appctx_t *ctx0) { void isc_app_finish(void) { - isc_app_ctxfinish((isc_appctx_t *)&isc_g_appctx); + isc_app_ctxfinish(&isc_g_appctx); } void @@ -352,33 +339,26 @@ isc_app_unblock(void) { isc_result_t isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) { - isc__appctx_t *ctx; + isc_appctx_t *ctx; REQUIRE(mctx != NULL); REQUIRE(ctxp != NULL && *ctxp == NULL); ctx = isc_mem_get(mctx, sizeof(*ctx)); - if (ctx == NULL) - return (ISC_R_NOMEMORY); - ctx->common.impmagic = APPCTX_MAGIC; - ctx->common.magic = ISCAPI_APPCTX_MAGIC; + ctx->magic = APPCTX_MAGIC; ctx->mctx = NULL; isc_mem_attach(mctx, &ctx->mctx); - ctx->taskmgr = NULL; - ctx->socketmgr = NULL; - ctx->timermgr = NULL; - - *ctxp = (isc_appctx_t *)ctx; + *ctxp = ctx; return (ISC_R_SUCCESS); } void isc_appctx_destroy(isc_appctx_t **ctxp) { - isc__appctx_t *ctx; + isc_appctx_t *ctx; REQUIRE(ctxp != NULL); ctx = (isc__appctx_t *)*ctxp; @@ -388,30 +368,3 @@ isc_appctx_destroy(isc_appctx_t **ctxp) { *ctxp = NULL; } - -void -isc_appctx_settaskmgr(isc_appctx_t *ctx0, isc_taskmgr_t *taskmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->taskmgr = taskmgr; -} - -void -isc_appctx_setsocketmgr(isc_appctx_t *ctx0, isc_socketmgr_t *socketmgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->socketmgr = socketmgr; -} - -void -isc_appctx_settimermgr(isc_appctx_t *ctx0, isc_timermgr_t *timermgr) { - isc__appctx_t *ctx = (isc__appctx_t *)ctx0; - - REQUIRE(VALID_APPCTX(ctx)); - - ctx->timermgr = timermgr; -} diff --git a/lib/isc/win32/libisc.def.in b/lib/isc/win32/libisc.def.in index 4b66b3c9c1..d00d32dd64 100644 --- a/lib/isc/win32/libisc.def.in +++ b/lib/isc/win32/libisc.def.in @@ -24,9 +24,6 @@ isc_app_start isc_app_unblock isc_appctx_create isc_appctx_destroy -isc_appctx_setsocketmgr -isc_appctx_settaskmgr -isc_appctx_settimermgr isc__buffer_activeregion isc__buffer_add isc__buffer_availableregion diff --git a/lib/isc/win32/socket.c b/lib/isc/win32/socket.c index 86d25bf418..f635223e55 100644 --- a/lib/isc/win32/socket.c +++ b/lib/isc/win32/socket.c @@ -3872,16 +3872,12 @@ isc_socketmgr_renderjson(isc_socketmgr_t *mgr, json_object *stats) { #endif /* HAVE_JSON */ isc_result_t -isc_socketmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, - isc_socketmgr_t **managerp) +isc_socketmgr_createinctx(isc_mem_t *mctx, isc_socketmgr_t **managerp) { isc_result_t result; result = isc_socketmgr_create(mctx, managerp); - if (result == ISC_R_SUCCESS) - isc_appctx_setsocketmgr(actx, *managerp); - return (result); } diff --git a/lib/samples/nsprobe.c b/lib/samples/nsprobe.c index 7fe3bb8803..d543dbd447 100644 --- a/lib/samples/nsprobe.c +++ b/lib/samples/nsprobe.c @@ -223,15 +223,15 @@ ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, if (result != ISC_R_SUCCESS) goto fail; - result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + result = isc_taskmgr_createinctx(*mctxp, 1, 0, taskmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + result = isc_socketmgr_createinctx(*mctxp, socketmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + result = isc_timermgr_createinctx(*mctxp, timermgrp); if (result != ISC_R_SUCCESS) goto fail; diff --git a/lib/samples/resolve.c b/lib/samples/resolve.c index b66d10b1fc..c2620d318f 100644 --- a/lib/samples/resolve.c +++ b/lib/samples/resolve.c @@ -379,13 +379,13 @@ main(int argc, char *argv[]) { result = isc_app_ctxstart(actx); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_taskmgr_createinctx(mctx, actx, 1, 0, &taskmgr); + result = isc_taskmgr_createinctx(mctx, 1, 0, &taskmgr); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_socketmgr_createinctx(mctx, actx, &socketmgr); + result = isc_socketmgr_createinctx(mctx, &socketmgr); if (result != ISC_R_SUCCESS) goto cleanup; - result = isc_timermgr_createinctx(mctx, actx, &timermgr); + result = isc_timermgr_createinctx(mctx, &timermgr); if (result != ISC_R_SUCCESS) goto cleanup; diff --git a/lib/samples/sample-async.c b/lib/samples/sample-async.c index 0d040e16e7..2d577a3ec5 100644 --- a/lib/samples/sample-async.c +++ b/lib/samples/sample-async.c @@ -105,15 +105,15 @@ ctxs_init(isc_mem_t **mctxp, isc_appctx_t **actxp, if (result != ISC_R_SUCCESS) goto fail; - result = isc_taskmgr_createinctx(*mctxp, *actxp, 1, 0, taskmgrp); + result = isc_taskmgr_createinctx(*mctxp, 1, 0, taskmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_socketmgr_createinctx(*mctxp, *actxp, socketmgrp); + result = isc_socketmgr_createinctx(*mctxp, socketmgrp); if (result != ISC_R_SUCCESS) goto fail; - result = isc_timermgr_createinctx(*mctxp, *actxp, timermgrp); + result = isc_timermgr_createinctx(*mctxp, timermgrp); if (result != ISC_R_SUCCESS) goto fail;