Merge unix/app.c and win32/app.c
The differences between two files are very minimal and most of the code is common. Merge those two files and use #ifdef WIN32 to include the right bits on Windows.
This commit is contained in:
@@ -26,7 +26,7 @@ CWARNINGS =
|
|||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
UNIXOBJS = unix/pk11_api.@O@ \
|
UNIXOBJS = unix/pk11_api.@O@ \
|
||||||
unix/app.@O@ unix/dir.@O@ unix/errno.@O@ \
|
unix/dir.@O@ unix/errno.@O@ \
|
||||||
unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
|
unix/errno2result.@O@ unix/file.@O@ unix/fsaccess.@O@ \
|
||||||
unix/interfaceiter.@O@ unix/meminfo.@O@ \
|
unix/interfaceiter.@O@ unix/meminfo.@O@ \
|
||||||
unix/net.@O@ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ \
|
unix/net.@O@ unix/os.@O@ unix/resource.@O@ unix/socket.@O@ \
|
||||||
@@ -42,7 +42,8 @@ WIN32OBJS = win32/condition.@O@ win32/dir.@O@ win32/errno.@O@ \
|
|||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
OBJS = pk11.@O@ pk11_result.@O@ \
|
OBJS = pk11.@O@ pk11_result.@O@ \
|
||||||
aes.@O@ assertions.@O@ backtrace.@O@ base32.@O@ base64.@O@ \
|
aes.@O@ app.@O@ assertions.@O@ \
|
||||||
|
backtrace.@O@ base32.@O@ base64.@O@ \
|
||||||
bind9.@O@ buffer.@O@ bufferlist.@O@ \
|
bind9.@O@ buffer.@O@ bufferlist.@O@ \
|
||||||
commandline.@O@ counter.@O@ crc64.@O@ error.@O@ entropy.@O@ \
|
commandline.@O@ counter.@O@ crc64.@O@ error.@O@ entropy.@O@ \
|
||||||
event.@O@ hash.@O@ ht.@O@ heap.@O@ hex.@O@ hmac.@O@ \
|
event.@O@ hash.@O@ ht.@O@ heap.@O@ hex.@O@ hmac.@O@ \
|
||||||
@@ -61,7 +62,8 @@ SYMTBLOBJS = backtrace-emptytbl.@O@
|
|||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
SRCS = pk11.c pk11_result.c \
|
SRCS = pk11.c pk11_result.c \
|
||||||
aes.c assertions.c backtrace.c base32.c base64.c bind9.c \
|
aes.c app.c assertions.c \
|
||||||
|
backtrace.c base32.c base64.c bind9.c \
|
||||||
buffer.c bufferlist.c commandline.c counter.c crc64.c \
|
buffer.c bufferlist.c commandline.c counter.c crc64.c \
|
||||||
entropy.c error.c event.c hash.c ht.c heap.c hex.c hmac.c \
|
entropy.c error.c event.c hash.c ht.c heap.c hex.c hmac.c \
|
||||||
httpd.c iterated_hash.c \
|
httpd.c iterated_hash.c \
|
||||||
|
|||||||
@@ -11,20 +11,19 @@
|
|||||||
|
|
||||||
/*! \file */
|
/*! \file */
|
||||||
|
|
||||||
#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <inttypes.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#ifdef HAVE_EPOLL
|
#endif /* WIN32 */
|
||||||
#include <sys/epoll.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <isc/platform.h>
|
#include <isc/platform.h>
|
||||||
#include <isc/atomic.h>
|
#include <isc/atomic.h>
|
||||||
@@ -38,26 +37,45 @@
|
|||||||
#include <isc/string.h>
|
#include <isc/string.h>
|
||||||
#include <isc/task.h>
|
#include <isc/task.h>
|
||||||
#include <isc/time.h>
|
#include <isc/time.h>
|
||||||
|
#include <isc/thread.h>
|
||||||
#include <isc/util.h>
|
#include <isc/util.h>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <process.h>
|
||||||
|
#else /* WIN32 */
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
/*%
|
/*%
|
||||||
* For BIND9 internal applications built with threads, we use a single app
|
* For BIND9 internal applications built with threads, we use a single app
|
||||||
* context and let multiple worker, I/O, timer threads do actual jobs.
|
* context and let multiple worker, I/O, timer threads do actual jobs.
|
||||||
* For other cases (including BIND9 built without threads) an app context acts
|
|
||||||
* as an event loop dispatching various events.
|
|
||||||
*/
|
*/
|
||||||
static pthread_t blockedthread;
|
|
||||||
|
static isc_thread_t blockedthread;
|
||||||
static atomic_bool is_running;
|
static atomic_bool is_running;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
/*
|
/*
|
||||||
* The application context of this module. This implementation actually
|
* We need to remember which thread is the main thread...
|
||||||
* doesn't use it. (This may change in the future).
|
*/
|
||||||
|
static isc_thread_t main_thread;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The application context of this module.
|
||||||
*/
|
*/
|
||||||
#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
|
#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
|
||||||
#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
|
#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define NUM_EVENTS 2
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RELOAD_EVENT,
|
||||||
|
SHUTDOWN_EVENT
|
||||||
|
};
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
struct isc_appctx {
|
struct isc_appctx {
|
||||||
unsigned int magic;
|
unsigned int magic;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
@@ -68,12 +86,17 @@ struct isc_appctx {
|
|||||||
atomic_bool want_shutdown;
|
atomic_bool want_shutdown;
|
||||||
atomic_bool want_reload;
|
atomic_bool want_reload;
|
||||||
atomic_bool blocked;
|
atomic_bool blocked;
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE hEvents[NUM_EVENTS];
|
||||||
|
#else /* WIN32 */
|
||||||
isc_mutex_t readylock;
|
isc_mutex_t readylock;
|
||||||
isc_condition_t ready;
|
isc_condition_t ready;
|
||||||
|
#endif /* WIN32 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static isc_appctx_t isc_g_appctx;
|
static isc_appctx_t isc_g_appctx;
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
static void
|
static void
|
||||||
handle_signal(int sig, void (*handler)(int)) {
|
handle_signal(int sig, void (*handler)(int)) {
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
@@ -90,13 +113,10 @@ handle_signal(int sig, void (*handler)(int)) {
|
|||||||
sig, strbuf);
|
sig, strbuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_app_ctxstart(isc_appctx_t *ctx) {
|
isc_app_ctxstart(isc_appctx_t *ctx) {
|
||||||
int presult;
|
|
||||||
sigset_t sset;
|
|
||||||
char strbuf[ISC_STRERRORSIZE];
|
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
REQUIRE(VALID_APPCTX(ctx));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -105,8 +125,10 @@ isc_app_ctxstart(isc_appctx_t *ctx) {
|
|||||||
|
|
||||||
isc_mutex_init(&ctx->lock);
|
isc_mutex_init(&ctx->lock);
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
isc_mutex_init(&ctx->readylock);
|
isc_mutex_init(&ctx->readylock);
|
||||||
isc_condition_init(&ctx->ready);
|
isc_condition_init(&ctx->ready);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
ISC_LIST_INIT(ctx->on_run);
|
ISC_LIST_INIT(ctx->on_run);
|
||||||
|
|
||||||
@@ -116,6 +138,19 @@ isc_app_ctxstart(isc_appctx_t *ctx) {
|
|||||||
atomic_init(&ctx->want_reload, false);
|
atomic_init(&ctx->want_reload, false);
|
||||||
atomic_init(&ctx->blocked, false);
|
atomic_init(&ctx->blocked, false);
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
main_thread = GetCurrentThread();
|
||||||
|
|
||||||
|
/* Create the reload event in a non-signaled state */
|
||||||
|
ctx->hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
|
||||||
|
/* Create the shutdown event in a non-signaled state */
|
||||||
|
ctx->hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
#else /* WIN32 */
|
||||||
|
int presult;
|
||||||
|
sigset_t sset;
|
||||||
|
char strbuf[ISC_STRERRORSIZE];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Always ignore SIGPIPE.
|
* Always ignore SIGPIPE.
|
||||||
*/
|
*/
|
||||||
@@ -150,6 +185,8 @@ isc_app_ctxstart(isc_appctx_t *ctx) {
|
|||||||
strbuf);
|
strbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,6 +230,7 @@ isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LOCK(&ctx->lock);
|
LOCK(&ctx->lock);
|
||||||
|
ISC_LINK_INIT(event, ev_link);
|
||||||
ISC_LIST_APPEND(ctx->on_run, event, ev_link);
|
ISC_LIST_APPEND(ctx->on_run, event, ev_link);
|
||||||
UNLOCK(&ctx->lock);
|
UNLOCK(&ctx->lock);
|
||||||
|
|
||||||
@@ -203,13 +241,15 @@ isc_result_t
|
|||||||
isc_app_ctxrun(isc_appctx_t *ctx) {
|
isc_app_ctxrun(isc_appctx_t *ctx) {
|
||||||
isc_event_t *event, *next_event;
|
isc_event_t *event, *next_event;
|
||||||
isc_task_t *task;
|
isc_task_t *task;
|
||||||
sigset_t sset;
|
|
||||||
int sig;
|
|
||||||
bool exp_false = false;
|
bool exp_false = false;
|
||||||
bool exp_true = true;
|
bool exp_true = true;
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
REQUIRE(VALID_APPCTX(ctx));
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
REQUIRE(main_thread == GetCurrentThread());
|
||||||
|
#endif
|
||||||
|
|
||||||
if (atomic_compare_exchange_weak_acq_rel(
|
if (atomic_compare_exchange_weak_acq_rel(
|
||||||
&ctx->running, &exp_false, true) == true)
|
&ctx->running, &exp_false, true) == true)
|
||||||
{
|
{
|
||||||
@@ -229,12 +269,14 @@ isc_app_ctxrun(isc_appctx_t *ctx) {
|
|||||||
UNLOCK(&ctx->lock);
|
UNLOCK(&ctx->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
/*
|
/*
|
||||||
* BIND9 internal tools using multiple contexts do not
|
* BIND9 internal tools using multiple contexts do not
|
||||||
* rely on signal. */
|
* rely on signal. */
|
||||||
if (isc_bind9 && ctx != &isc_g_appctx) {
|
if (isc_bind9 && ctx != &isc_g_appctx) {
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
}
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is no danger if isc_app_shutdown() is called before we
|
* There is no danger if isc_app_shutdown() is called before we
|
||||||
@@ -243,7 +285,33 @@ isc_app_ctxrun(isc_appctx_t *ctx) {
|
|||||||
* sigwait().
|
* sigwait().
|
||||||
*/
|
*/
|
||||||
while (atomic_load_acquire(&ctx->want_shutdown) == false) {
|
while (atomic_load_acquire(&ctx->want_shutdown) == false) {
|
||||||
|
#ifdef WIN32
|
||||||
|
DWORD dwWaitResult = \
|
||||||
|
WaitForMultipleObjects(NUM_EVENTS, ctx->hEvents,
|
||||||
|
FALSE, INFINITE);
|
||||||
|
|
||||||
|
/* See why we returned */
|
||||||
|
|
||||||
|
if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
|
||||||
|
/*
|
||||||
|
* The return was due to one of the events
|
||||||
|
* being signaled
|
||||||
|
*/
|
||||||
|
switch (WaitSucceededIndex(dwWaitResult)) {
|
||||||
|
case RELOAD_EVENT:
|
||||||
|
atomic_store_release(&ctx->want_reload, true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SHUTDOWN_EVENT:
|
||||||
|
atomic_store_release(&ctx->want_shutdown, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* WIN32 */
|
||||||
if (isc_bind9) {
|
if (isc_bind9) {
|
||||||
|
sigset_t sset;
|
||||||
|
int sig;
|
||||||
/*
|
/*
|
||||||
* BIND9 internal; single context:
|
* BIND9 internal; single context:
|
||||||
* Wait for SIGHUP, SIGINT, or SIGTERM.
|
* Wait for SIGHUP, SIGINT, or SIGTERM.
|
||||||
@@ -289,7 +357,7 @@ isc_app_ctxrun(isc_appctx_t *ctx) {
|
|||||||
UNLOCK(&ctx->readylock);
|
UNLOCK(&ctx->readylock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
exp_true = true;
|
exp_true = true;
|
||||||
if (atomic_compare_exchange_weak_acq_rel(&ctx->want_reload,
|
if (atomic_compare_exchange_weak_acq_rel(&ctx->want_reload,
|
||||||
&exp_true,
|
&exp_true,
|
||||||
@@ -341,6 +409,9 @@ isc_app_ctxshutdown(isc_appctx_t *ctx) {
|
|||||||
&exp_false,
|
&exp_false,
|
||||||
true))
|
true))
|
||||||
{
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
SetEvent(ctx->hEvents[SHUTDOWN_EVENT]);
|
||||||
|
#else /* WIN32 */
|
||||||
if (isc_bind9 && ctx != &isc_g_appctx) {
|
if (isc_bind9 && ctx != &isc_g_appctx) {
|
||||||
/* BIND9 internal, but using multiple contexts */
|
/* BIND9 internal, but using multiple contexts */
|
||||||
atomic_store_release(&ctx->want_shutdown, true);
|
atomic_store_release(&ctx->want_shutdown, true);
|
||||||
@@ -359,6 +430,7 @@ isc_app_ctxshutdown(isc_appctx_t *ctx) {
|
|||||||
atomic_store_release(&ctx->want_shutdown, true);
|
atomic_store_release(&ctx->want_shutdown, true);
|
||||||
SIGNAL(&ctx->ready);
|
SIGNAL(&ctx->ready);
|
||||||
}
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -378,6 +450,9 @@ isc_app_ctxsuspend(isc_appctx_t *ctx) {
|
|||||||
* Don't send the reload signal if we're shutting down.
|
* Don't send the reload signal if we're shutting down.
|
||||||
*/
|
*/
|
||||||
if (atomic_load_acquire(&ctx->shutdown_requested) == false) {
|
if (atomic_load_acquire(&ctx->shutdown_requested) == false) {
|
||||||
|
#ifdef WIN32
|
||||||
|
SetEvent(ctx->hEvents[RELOAD_EVENT]);
|
||||||
|
#else /* WIN32 */
|
||||||
if (isc_bind9 && ctx != &isc_g_appctx) {
|
if (isc_bind9 && ctx != &isc_g_appctx) {
|
||||||
/* BIND9 internal, but using multiple contexts */
|
/* BIND9 internal, but using multiple contexts */
|
||||||
atomic_store_release(&ctx->want_reload, true);
|
atomic_store_release(&ctx->want_reload, true);
|
||||||
@@ -396,7 +471,7 @@ isc_app_ctxsuspend(isc_appctx_t *ctx) {
|
|||||||
atomic_store_release(&ctx->want_reload, true);
|
atomic_store_release(&ctx->want_reload, true);
|
||||||
SIGNAL(&ctx->ready);
|
SIGNAL(&ctx->ready);
|
||||||
}
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +485,10 @@ isc_app_ctxfinish(isc_appctx_t *ctx) {
|
|||||||
REQUIRE(VALID_APPCTX(ctx));
|
REQUIRE(VALID_APPCTX(ctx));
|
||||||
|
|
||||||
isc_mutex_destroy(&ctx->lock);
|
isc_mutex_destroy(&ctx->lock);
|
||||||
|
#ifndef WIN32
|
||||||
isc_mutex_destroy(&ctx->readylock);
|
isc_mutex_destroy(&ctx->readylock);
|
||||||
isc_condition_destroy(&ctx->ready);
|
isc_condition_destroy(&ctx->ready);
|
||||||
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -421,21 +498,25 @@ isc_app_finish(void) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
isc_app_block(void) {
|
isc_app_block(void) {
|
||||||
sigset_t sset;
|
bool exp_false = false;
|
||||||
REQUIRE(isc_g_appctx.running);
|
REQUIRE(atomic_load_acquire(&isc_g_appctx.running));
|
||||||
REQUIRE(!isc_g_appctx.blocked);
|
REQUIRE(atomic_compare_exchange_weak_acq_rel(&isc_g_appctx.blocked,
|
||||||
|
&exp_false, true));
|
||||||
|
|
||||||
atomic_store_release(&isc_g_appctx.blocked, true);
|
#ifdef WIN32
|
||||||
|
blockedthread = GetCurrentThread();
|
||||||
|
#else /* WIN32 */
|
||||||
|
sigset_t sset;
|
||||||
blockedthread = pthread_self();
|
blockedthread = pthread_self();
|
||||||
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
|
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
|
||||||
sigaddset(&sset, SIGINT) == 0 &&
|
sigaddset(&sset, SIGINT) == 0 &&
|
||||||
sigaddset(&sset, SIGTERM) == 0);
|
sigaddset(&sset, SIGTERM) == 0);
|
||||||
RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
|
RUNTIME_CHECK(pthread_sigmask(SIG_UNBLOCK, &sset, NULL) == 0);
|
||||||
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc_app_unblock(void) {
|
isc_app_unblock(void) {
|
||||||
sigset_t sset;
|
|
||||||
bool exp_true = true;
|
bool exp_true = true;
|
||||||
|
|
||||||
REQUIRE(atomic_load_acquire(&isc_g_appctx.running));
|
REQUIRE(atomic_load_acquire(&isc_g_appctx.running));
|
||||||
@@ -444,12 +525,17 @@ isc_app_unblock(void) {
|
|||||||
&exp_true,
|
&exp_true,
|
||||||
false));
|
false));
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
REQUIRE(blockedthread == GetCurrentThread());
|
||||||
|
#else /* WIN32 */
|
||||||
REQUIRE(blockedthread == pthread_self());
|
REQUIRE(blockedthread == pthread_self());
|
||||||
|
|
||||||
|
sigset_t sset;
|
||||||
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
|
RUNTIME_CHECK(sigemptyset(&sset) == 0 &&
|
||||||
sigaddset(&sset, SIGINT) == 0 &&
|
sigaddset(&sset, SIGINT) == 0 &&
|
||||||
sigaddset(&sset, SIGTERM) == 0);
|
sigaddset(&sset, SIGTERM) == 0);
|
||||||
RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
|
RUNTIME_CHECK(pthread_sigmask(SIG_BLOCK, &sset, NULL) == 0);
|
||||||
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -460,8 +546,6 @@ isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
|
|||||||
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
||||||
|
|
||||||
ctx = isc_mem_get(mctx, sizeof(*ctx));
|
ctx = isc_mem_get(mctx, sizeof(*ctx));
|
||||||
if (ctx == NULL)
|
|
||||||
return (ISC_R_NOMEMORY);
|
|
||||||
|
|
||||||
ctx->magic = APPCTX_MAGIC;
|
ctx->magic = APPCTX_MAGIC;
|
||||||
|
|
||||||
@@ -479,8 +563,8 @@ isc_appctx_destroy(isc_appctx_t **ctxp) {
|
|||||||
|
|
||||||
REQUIRE(ctxp != NULL);
|
REQUIRE(ctxp != NULL);
|
||||||
ctx = *ctxp;
|
ctx = *ctxp;
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
*ctxp = NULL;
|
*ctxp = NULL;
|
||||||
|
REQUIRE(VALID_APPCTX(ctx));
|
||||||
|
|
||||||
ctx->magic = 0;
|
ctx->magic = 0;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ CWARNINGS =
|
|||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
OBJS = pk11_api.@O@ \
|
OBJS = pk11_api.@O@ \
|
||||||
app.@O@ dir.@O@ errno.@O@ errno2result.@O@ \
|
dir.@O@ errno.@O@ errno2result.@O@ \
|
||||||
file.@O@ fsaccess.@O@ interfaceiter.@O@ \
|
file.@O@ fsaccess.@O@ interfaceiter.@O@ \
|
||||||
meminfo.@O@ \
|
meminfo.@O@ \
|
||||||
net.@O@ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
|
net.@O@ os.@O@ resource.@O@ socket.@O@ stdio.@O@ stdtime.@O@ \
|
||||||
@@ -30,7 +30,7 @@ OBJS = pk11_api.@O@ \
|
|||||||
|
|
||||||
# Alphabetically
|
# Alphabetically
|
||||||
SRCS = pk11_api.c \
|
SRCS = pk11_api.c \
|
||||||
app.c dir.c errno.c errno2result.c \
|
dir.c errno.c errno2result.c \
|
||||||
file.c fsaccess.c interfaceiter.c meminfo.c \
|
file.c fsaccess.c interfaceiter.c meminfo.c \
|
||||||
net.c os.c resource.c socket.c stdio.c stdtime.c \
|
net.c os.c resource.c socket.c stdio.c stdtime.c \
|
||||||
syslog.c time.c
|
syslog.c time.c
|
||||||
|
|||||||
@@ -1,353 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*
|
|
||||||
* See the COPYRIGHT file distributed with this work for additional
|
|
||||||
* information regarding copyright ownership.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
#include <isc/app.h>
|
|
||||||
#include <isc/atomic.h>
|
|
||||||
#include <isc/condition.h>
|
|
||||||
#include <isc/mem.h>
|
|
||||||
#include <isc/mutex.h>
|
|
||||||
#include <isc/event.h>
|
|
||||||
#include <isc/platform.h>
|
|
||||||
#include <isc/string.h>
|
|
||||||
#include <isc/task.h>
|
|
||||||
#include <isc/time.h>
|
|
||||||
#include <isc/util.h>
|
|
||||||
#include <isc/thread.h>
|
|
||||||
|
|
||||||
/*%
|
|
||||||
* For BIND9 internal applications built with threads, we use a single app
|
|
||||||
* context and let multiple worker, I/O, timer threads do actual jobs.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static isc_thread_t blockedthread;
|
|
||||||
static atomic_bool is_running;
|
|
||||||
|
|
||||||
#define APPCTX_MAGIC ISC_MAGIC('A', 'p', 'c', 'x')
|
|
||||||
#define VALID_APPCTX(c) ISC_MAGIC_VALID(c, APPCTX_MAGIC)
|
|
||||||
|
|
||||||
/* Events to wait for */
|
|
||||||
|
|
||||||
#define NUM_EVENTS 2
|
|
||||||
|
|
||||||
enum {
|
|
||||||
RELOAD_EVENT,
|
|
||||||
SHUTDOWN_EVENT
|
|
||||||
};
|
|
||||||
|
|
||||||
struct isc_appctx {
|
|
||||||
unsigned int magic;
|
|
||||||
isc_mem_t *mctx;
|
|
||||||
isc_eventlist_t on_run;
|
|
||||||
isc_mutex_t lock;
|
|
||||||
atomic_bool shutdown_requested;
|
|
||||||
atomic_bool running;
|
|
||||||
/*
|
|
||||||
* We assume that 'want_shutdown' can be read and written atomically.
|
|
||||||
*/
|
|
||||||
atomic_bool want_shutdown;
|
|
||||||
/*
|
|
||||||
* We assume that 'want_reload' can be read and written atomically.
|
|
||||||
*/
|
|
||||||
atomic_bool want_reload;
|
|
||||||
|
|
||||||
atomic_bool blocked;
|
|
||||||
|
|
||||||
HANDLE hEvents[NUM_EVENTS];
|
|
||||||
};
|
|
||||||
|
|
||||||
static isc_appctx_t isc_g_appctx;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to remember which thread is the main thread...
|
|
||||||
*/
|
|
||||||
static isc_thread_t main_thread;
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_app_ctxstart(isc_appctx_t *ctx) {
|
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Start an ISC library application.
|
|
||||||
*/
|
|
||||||
|
|
||||||
main_thread = GetCurrentThread();
|
|
||||||
|
|
||||||
isc_mutex_init(&ctx->lock);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* Create the reload event in a non-signaled state */
|
|
||||||
ctx->hEvents[RELOAD_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
||||||
|
|
||||||
/* Create the shutdown event in a non-signaled state */
|
|
||||||
ctx->hEvents[SHUTDOWN_EVENT] = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
||||||
|
|
||||||
ISC_LIST_INIT(ctx->on_run);
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_app_start(void) {
|
|
||||||
isc_g_appctx.magic = APPCTX_MAGIC;
|
|
||||||
isc_g_appctx.mctx = NULL;
|
|
||||||
/* The remaining members will be initialized in ctxstart() */
|
|
||||||
|
|
||||||
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_g_appctx, mctx, task, action, arg));
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_app_ctxonrun(isc_appctx_t *ctx, isc_mem_t *mctx, isc_task_t *task,
|
|
||||||
isc_taskaction_t action, void *arg)
|
|
||||||
{
|
|
||||||
isc_event_t *event;
|
|
||||||
isc_task_t *cloned_task = NULL;
|
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
if (atomic_load_acquire(&ctx->running)) {
|
|
||||||
return (ISC_R_ALREADYRUNNING);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that we store the task to which we're going to send the event
|
|
||||||
* in the event's "sender" field.
|
|
||||||
*/
|
|
||||||
isc_task_attach(task, &cloned_task);
|
|
||||||
event = isc_event_allocate(mctx, cloned_task, ISC_APPEVENT_SHUTDOWN,
|
|
||||||
action, arg, sizeof(*event));
|
|
||||||
if (event == NULL) {
|
|
||||||
return (ISC_R_NOMEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCK(&ctx->lock);
|
|
||||||
ISC_LINK_INIT(event, ev_link);
|
|
||||||
ISC_LIST_APPEND(ctx->on_run, event, ev_link);
|
|
||||||
UNLOCK(&ctx->lock);
|
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_app_ctxrun(isc_appctx_t *ctx) {
|
|
||||||
bool exp_true = true;
|
|
||||||
bool exp_false = false;
|
|
||||||
isc_event_t *event, *next_event;
|
|
||||||
isc_task_t *task;
|
|
||||||
HANDLE *pHandles = NULL;
|
|
||||||
DWORD dwWaitResult;
|
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
|
|
||||||
REQUIRE(main_thread == GetCurrentThread());
|
|
||||||
|
|
||||||
LOCK(&ctx->lock);
|
|
||||||
if (atomic_compare_exchange_weak(&ctx->running, &exp_false, true)) {
|
|
||||||
/*
|
|
||||||
* Post any on-run events (in FIFO order).
|
|
||||||
*/
|
|
||||||
for (event = ISC_LIST_HEAD(ctx->on_run);
|
|
||||||
event != NULL;
|
|
||||||
event = next_event) {
|
|
||||||
next_event = ISC_LIST_NEXT(event, ev_link);
|
|
||||||
ISC_LIST_UNLINK(ctx->on_run, event, ev_link);
|
|
||||||
task = event->ev_sender;
|
|
||||||
event->ev_sender = NULL;
|
|
||||||
isc_task_sendanddetach(&task, &event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
UNLOCK(&ctx->lock);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* There is no danger if isc_app_shutdown() is called before we wait
|
|
||||||
* for events.
|
|
||||||
*/
|
|
||||||
|
|
||||||
while (atomic_load_acquire(&ctx->want_shutdown) == false) {
|
|
||||||
dwWaitResult = WaitForMultipleObjects(NUM_EVENTS, ctx->hEvents,
|
|
||||||
FALSE, INFINITE);
|
|
||||||
|
|
||||||
/* See why we returned */
|
|
||||||
|
|
||||||
if (WaitSucceeded(dwWaitResult, NUM_EVENTS)) {
|
|
||||||
/*
|
|
||||||
* The return was due to one of the events
|
|
||||||
* being signaled
|
|
||||||
*/
|
|
||||||
switch (WaitSucceededIndex(dwWaitResult)) {
|
|
||||||
case RELOAD_EVENT:
|
|
||||||
atomic_store_release(&ctx->want_reload, true);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SHUTDOWN_EVENT:
|
|
||||||
atomic_store_release(&ctx->want_shutdown, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exp_true = true;
|
|
||||||
if (atomic_compare_exchange_weak(&ctx->want_reload,
|
|
||||||
&exp_true, false))
|
|
||||||
{
|
|
||||||
return (ISC_R_RELOAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atomic_load_acquire(&ctx->want_shutdown) &&
|
|
||||||
atomic_load_acquire(&ctx->blocked)) {
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_app_run(void) {
|
|
||||||
bool exp_false = false;
|
|
||||||
isc_result_t result;
|
|
||||||
|
|
||||||
REQUIRE(atomic_compare_exchange_weak(&is_running, &exp_false, true));
|
|
||||||
result = isc_app_ctxrun(&isc_g_appctx);
|
|
||||||
atomic_store_release(&is_running, false);
|
|
||||||
|
|
||||||
return (result);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
isc_app_isrunning() {
|
|
||||||
return (is_running);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_ctxshutdown(isc_appctx_t *ctx) {
|
|
||||||
bool exp_false = false;
|
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
REQUIRE(atomic_load_acquire(&ctx->running));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If ctx->shutdown_requested == true, we are already shutting
|
|
||||||
* down and we want to just bail out.
|
|
||||||
*/
|
|
||||||
if (atomic_compare_exchange_weak(&ctx->shutdown_requested,
|
|
||||||
&exp_false, true))
|
|
||||||
{
|
|
||||||
SetEvent(ctx->hEvents[SHUTDOWN_EVENT]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_shutdown(void) {
|
|
||||||
isc_app_ctxshutdown(&isc_g_appctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_ctxsuspend(isc_appctx_t *ctx) {
|
|
||||||
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
REQUIRE(atomic_load(&ctx->running));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't send the reload signal if we're shutting down.
|
|
||||||
*/
|
|
||||||
if (atomic_load_acquire(&ctx->shutdown_requested) == false) {
|
|
||||||
SetEvent(ctx->hEvents[RELOAD_EVENT]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_reload(void) {
|
|
||||||
isc_app_ctxsuspend(&isc_g_appctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_ctxfinish(isc_appctx_t *ctx) {
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
|
|
||||||
isc_mutex_destroy(&ctx->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_finish(void) {
|
|
||||||
isc_app_ctxfinish(&isc_g_appctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_block(void) {
|
|
||||||
bool exp_false = false;
|
|
||||||
|
|
||||||
REQUIRE(atomic_load_acquire(&isc_g_appctx.running));
|
|
||||||
REQUIRE(atomic_compare_exchange_weak(&isc_g_appctx.blocked,
|
|
||||||
&exp_false, true));
|
|
||||||
|
|
||||||
blockedthread = GetCurrentThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_app_unblock(void) {
|
|
||||||
bool exp_true = true;
|
|
||||||
|
|
||||||
REQUIRE(atomic_load_acquire(&isc_g_appctx.running));
|
|
||||||
REQUIRE(atomic_compare_exchange_weak(&isc_g_appctx.blocked,
|
|
||||||
&exp_true, false));
|
|
||||||
REQUIRE(blockedthread == GetCurrentThread());
|
|
||||||
}
|
|
||||||
|
|
||||||
isc_result_t
|
|
||||||
isc_appctx_create(isc_mem_t *mctx, isc_appctx_t **ctxp) {
|
|
||||||
isc_appctx_t *ctx;
|
|
||||||
|
|
||||||
REQUIRE(mctx != NULL);
|
|
||||||
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
|
||||||
|
|
||||||
ctx = isc_mem_get(mctx, sizeof(*ctx));
|
|
||||||
|
|
||||||
ctx->magic = APPCTX_MAGIC;
|
|
||||||
|
|
||||||
ctx->mctx = NULL;
|
|
||||||
isc_mem_attach(mctx, &ctx->mctx);
|
|
||||||
|
|
||||||
*ctxp = ctx;
|
|
||||||
|
|
||||||
return (ISC_R_SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc_appctx_destroy(isc_appctx_t **ctxp) {
|
|
||||||
isc_appctx_t *ctx;
|
|
||||||
|
|
||||||
REQUIRE(ctxp != NULL);
|
|
||||||
ctx = *ctxp;
|
|
||||||
*ctxp = NULL;
|
|
||||||
REQUIRE(VALID_APPCTX(ctx));
|
|
||||||
|
|
||||||
isc_mem_putanddetach(&ctx->mctx, ctx, sizeof(*ctx));
|
|
||||||
}
|
|
||||||
@@ -377,9 +377,6 @@
|
|||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="app.c">
|
|
||||||
<Filter>Win32 Source Files</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="condition.c">
|
<ClCompile Include="condition.c">
|
||||||
<Filter>Win32 Source Files</Filter>
|
<Filter>Win32 Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@@ -457,6 +454,9 @@
|
|||||||
<ClCompile Include="..\aes.c">
|
<ClCompile Include="..\aes.c">
|
||||||
<Filter>Win32 Source Files</Filter>
|
<Filter>Win32 Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\app.c">
|
||||||
|
<Filter>Win32 Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\assertions.c">
|
<ClCompile Include="..\assertions.c">
|
||||||
<Filter>Library Source Files</Filter>
|
<Filter>Library Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|||||||
@@ -416,6 +416,7 @@ copy InstallFiles ..\Build\Release\
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\aes.c" />
|
<ClCompile Include="..\aes.c" />
|
||||||
|
<ClCompile Include="..\app.c" />
|
||||||
<ClCompile Include="..\assertions.c" />
|
<ClCompile Include="..\assertions.c" />
|
||||||
<ClCompile Include="..\backtrace-emptytbl.c" />
|
<ClCompile Include="..\backtrace-emptytbl.c" />
|
||||||
<ClCompile Include="..\backtrace.c" />
|
<ClCompile Include="..\backtrace.c" />
|
||||||
@@ -473,7 +474,6 @@ copy InstallFiles ..\Build\Release\
|
|||||||
<ClCompile Include="..\pk11.c" />
|
<ClCompile Include="..\pk11.c" />
|
||||||
<ClCompile Include="..\pk11_result.c" />
|
<ClCompile Include="..\pk11_result.c" />
|
||||||
@END PKCS11
|
@END PKCS11
|
||||||
<ClCompile Include="app.c" />
|
|
||||||
<ClCompile Include="condition.c" />
|
<ClCompile Include="condition.c" />
|
||||||
<ClCompile Include="dir.c" />
|
<ClCompile Include="dir.c" />
|
||||||
<ClCompile Include="DLLMain.c" />
|
<ClCompile Include="DLLMain.c" />
|
||||||
|
|||||||
@@ -2122,6 +2122,7 @@
|
|||||||
./lib/isc/Kyuafile X 2017,2018,2019
|
./lib/isc/Kyuafile X 2017,2018,2019
|
||||||
./lib/isc/aes.c C 2014,2016,2017,2018,2019
|
./lib/isc/aes.c C 2014,2016,2017,2018,2019
|
||||||
./lib/isc/api X 1999,2000,2001,2006,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
./lib/isc/api X 1999,2000,2001,2006,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
||||||
|
./lib/isc/app.c C 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2013,2014,2015,2016,2017,2018,2019
|
||||||
./lib/isc/assertions.c C 1997,1998,1999,2000,2001,2004,2005,2007,2008,2009,2015,2016,2018,2019
|
./lib/isc/assertions.c C 1997,1998,1999,2000,2001,2004,2005,2007,2008,2009,2015,2016,2018,2019
|
||||||
./lib/isc/backtrace-emptytbl.c C 2009,2016,2018,2019
|
./lib/isc/backtrace-emptytbl.c C 2009,2016,2018,2019
|
||||||
./lib/isc/backtrace.c C 2009,2013,2014,2015,2016,2018,2019
|
./lib/isc/backtrace.c C 2009,2013,2014,2015,2016,2018,2019
|
||||||
@@ -2319,7 +2320,6 @@
|
|||||||
./lib/isc/timer.c C 1998,1999,2000,2001,2002,2004,2005,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
./lib/isc/timer.c C 1998,1999,2000,2001,2002,2004,2005,2007,2008,2009,2011,2012,2013,2014,2015,2016,2017,2018,2019
|
||||||
./lib/isc/timer_p.h C 2000,2001,2004,2005,2007,2009,2016,2017,2018,2019
|
./lib/isc/timer_p.h C 2000,2001,2004,2005,2007,2009,2016,2017,2018,2019
|
||||||
./lib/isc/tm.c C 2014,2016,2018,2019
|
./lib/isc/tm.c C 2014,2016,2018,2019
|
||||||
./lib/isc/unix/app.c C 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2013,2014,2015,2016,2017,2018,2019
|
|
||||||
./lib/isc/unix/dir.c C 1999,2000,2001,2004,2005,2007,2008,2009,2011,2012,2016,2017,2018,2019
|
./lib/isc/unix/dir.c C 1999,2000,2001,2004,2005,2007,2008,2009,2011,2012,2016,2017,2018,2019
|
||||||
./lib/isc/unix/errno.c C 2016,2018,2019
|
./lib/isc/unix/errno.c C 2016,2018,2019
|
||||||
./lib/isc/unix/errno2result.c C 2000,2001,2002,2004,2005,2007,2011,2012,2013,2016,2018,2019
|
./lib/isc/unix/errno2result.c C 2000,2001,2002,2004,2005,2007,2011,2012,2013,2016,2018,2019
|
||||||
@@ -2351,7 +2351,6 @@
|
|||||||
./lib/isc/unix/time.c C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2011,2012,2014,2015,2016,2017,2018,2019
|
./lib/isc/unix/time.c C 1998,1999,2000,2001,2003,2004,2005,2006,2007,2008,2011,2012,2014,2015,2016,2017,2018,2019
|
||||||
./lib/isc/version.c C 1998,1999,2000,2001,2004,2005,2007,2016,2018,2019
|
./lib/isc/version.c C 1998,1999,2000,2001,2004,2005,2007,2016,2018,2019
|
||||||
./lib/isc/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019
|
./lib/isc/win32/DLLMain.c C 2001,2004,2007,2016,2018,2019
|
||||||
./lib/isc/win32/app.c C 1999,2000,2001,2004,2007,2009,2013,2014,2016,2018,2019
|
|
||||||
./lib/isc/win32/condition.c C 1998,1999,2000,2001,2004,2006,2007,2016,2018,2019
|
./lib/isc/win32/condition.c C 1998,1999,2000,2001,2004,2006,2007,2016,2018,2019
|
||||||
./lib/isc/win32/dir.c C 1999,2000,2001,2004,2007,2008,2009,2011,2012,2013,2016,2017,2018,2019
|
./lib/isc/win32/dir.c C 1999,2000,2001,2004,2007,2008,2009,2011,2012,2013,2016,2017,2018,2019
|
||||||
./lib/isc/win32/errno.c C 2016,2018,2019
|
./lib/isc/win32/errno.c C 2016,2018,2019
|
||||||
|
|||||||
Reference in New Issue
Block a user