void ub_ctx_delete(struct ub_ctx* ctx) { struct alloc_cache* a, *na; int do_stop = 1; if(!ctx) return; /* see if bg thread is created and if threads have been killed */ /* no locks, because those may be held by terminated threads */ /* for processes the read pipe is closed and we see that on read */ #ifdef HAVE_PTHREAD if(ctx->created_bg && ctx->dothread) { if(pthread_kill(ctx->bg_tid, 0) == ESRCH) { /* thread has been killed */ do_stop = 0; } } #endif /* HAVE_PTHREAD */ if(do_stop) ub_stop_bg(ctx); libworker_delete_event(ctx->event_worker); modstack_desetup(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { na = a->super; a->super = &ctx->superalloc; alloc_clear(a); free(a); a = na; } local_zones_delete(ctx->local_zones); lock_basic_destroy(&ctx->qqpipe_lock); lock_basic_destroy(&ctx->rrpipe_lock); lock_basic_destroy(&ctx->cfglock); tube_delete(ctx->qq_pipe); tube_delete(ctx->rr_pipe); if(ctx->env) { slabhash_delete(ctx->env->msg_cache); rrset_cache_delete(ctx->env->rrset_cache); infra_delete(ctx->env->infra_cache); config_delete(ctx->env->cfg); edns_known_options_delete(ctx->env); auth_zones_delete(ctx->env->auth_zones); free(ctx->env); } ub_randfree(ctx->seed_rnd); alloc_clear(&ctx->superalloc); traverse_postorder(&ctx->queries, delq, NULL); free(ctx); #ifdef USE_WINSOCK WSACleanup(); #endif }
struct ub_ctx* ub_ctx_create(void) { struct ub_ctx* ctx = ub_ctx_create_nopipe(); if(!ctx) return NULL; if((ctx->qq_pipe = tube_create()) == NULL) { int e = errno; ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); free(ctx->env); free(ctx); errno = e; return NULL; } if((ctx->rr_pipe = tube_create()) == NULL) { int e = errno; tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); free(ctx->env); free(ctx); errno = e; return NULL; } return ctx; }
struct tube* tube_create(void) { struct tube* tube = (struct tube*)calloc(1, sizeof(*tube)); int sv[2]; if(!tube) { int err = errno; log_err("tube_create: out of memory"); errno = err; return NULL; } tube->sr = -1; tube->sw = -1; if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { int err = errno; log_err("socketpair: %s", strerror(errno)); free(tube); errno = err; return NULL; } tube->sr = sv[0]; tube->sw = sv[1]; if(!fd_set_nonblock(tube->sr) || !fd_set_nonblock(tube->sw)) { int err = errno; log_err("tube: cannot set nonblocking"); tube_delete(tube); errno = err; return NULL; } return tube; }
/** * Close all pipes except for the numbered thread. * @param daemon: daemon to close pipes in. * @param thr: thread number 0..num-1 of thread to skip. */ static void close_other_pipes(struct daemon* daemon, int thr) { int i; for(i=0; i<daemon->num; i++) if(i!=thr) { if(i==0) { /* only close read part, need to write stats */ tube_close_read(daemon->workers[i]->cmd); } else { /* complete close channel to others */ tube_delete(daemon->workers[i]->cmd); daemon->workers[i]->cmd = NULL; } } }
struct ub_ctx* ub_ctx_create(void) { struct ub_ctx* ctx; unsigned int seed; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif log_init(NULL, 0, NULL); /* logs to stderr */ log_ident_set("libunbound"); #ifdef USE_WINSOCK if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) { log_err("could not init winsock. WSAStartup: %s", wsa_strerror(r)); return NULL; } #endif verbosity = 0; /* errors only */ checklock_start(); ctx = (struct ub_ctx*)calloc(1, sizeof(*ctx)); if(!ctx) { errno = ENOMEM; return NULL; } alloc_init(&ctx->superalloc, NULL, 0); seed = (unsigned int)time(NULL) ^ (unsigned int)getpid(); if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) { seed = 0; ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } seed = 0; if((ctx->qq_pipe = tube_create()) == NULL) { int e = errno; ub_randfree(ctx->seed_rnd); free(ctx); errno = e; return NULL; } if((ctx->rr_pipe = tube_create()) == NULL) { int e = errno; tube_delete(ctx->qq_pipe); ub_randfree(ctx->seed_rnd); free(ctx); errno = e; return NULL; } lock_basic_init(&ctx->qqpipe_lock); lock_basic_init(&ctx->rrpipe_lock); lock_basic_init(&ctx->cfglock); ctx->env = (struct module_env*)calloc(1, sizeof(*ctx->env)); if(!ctx->env) { tube_delete(ctx->qq_pipe); tube_delete(ctx->rr_pipe); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } ctx->env->cfg = config_create_forlib(); if(!ctx->env->cfg) { tube_delete(ctx->qq_pipe); tube_delete(ctx->rr_pipe); free(ctx->env); ub_randfree(ctx->seed_rnd); free(ctx); errno = ENOMEM; return NULL; } ctx->env->alloc = &ctx->superalloc; ctx->env->worker = NULL; ctx->env->need_to_validate = 0; modstack_init(&ctx->mods); rbtree_init(&ctx->queries, &context_query_cmp); return ctx; }
void ub_ctx_delete(struct ub_ctx* ctx) { struct alloc_cache* a, *na; if(!ctx) return; /* stop the bg thread */ lock_basic_lock(&ctx->cfglock); if(ctx->created_bg) { uint8_t* msg; uint32_t len; uint32_t cmd = UB_LIBCMD_QUIT; lock_basic_unlock(&ctx->cfglock); lock_basic_lock(&ctx->qqpipe_lock); (void)tube_write_msg(ctx->qq_pipe, (uint8_t*)&cmd, (uint32_t)sizeof(cmd), 0); lock_basic_unlock(&ctx->qqpipe_lock); lock_basic_lock(&ctx->rrpipe_lock); while(tube_read_msg(ctx->rr_pipe, &msg, &len, 0)) { /* discard all results except a quit confirm */ if(context_serial_getcmd(msg, len) == UB_LIBCMD_QUIT) { free(msg); break; } free(msg); } lock_basic_unlock(&ctx->rrpipe_lock); /* if bg worker is a thread, wait for it to exit, so that all * resources are really gone. */ lock_basic_lock(&ctx->cfglock); if(ctx->dothread) { lock_basic_unlock(&ctx->cfglock); ub_thread_join(ctx->bg_tid); } else { lock_basic_unlock(&ctx->cfglock); } } else { lock_basic_unlock(&ctx->cfglock); } modstack_desetup(&ctx->mods, ctx->env); a = ctx->alloc_list; while(a) { na = a->super; a->super = &ctx->superalloc; alloc_clear(a); free(a); a = na; } local_zones_delete(ctx->local_zones); lock_basic_destroy(&ctx->qqpipe_lock); lock_basic_destroy(&ctx->rrpipe_lock); lock_basic_destroy(&ctx->cfglock); tube_delete(ctx->qq_pipe); tube_delete(ctx->rr_pipe); if(ctx->env) { slabhash_delete(ctx->env->msg_cache); rrset_cache_delete(ctx->env->rrset_cache); infra_delete(ctx->env->infra_cache); config_delete(ctx->env->cfg); free(ctx->env); } ub_randfree(ctx->seed_rnd); alloc_clear(&ctx->superalloc); traverse_postorder(&ctx->queries, delq, NULL); free(ctx); #ifdef USE_WINSOCK WSACleanup(); #endif }