Пример #1
0
/** do control command coming into bg server */
static void
libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
{
	switch(context_serial_getcmd(msg, len)) {
		default:
		case UB_LIBCMD_ANSWER:
			log_err("unknown command for bg worker %d", 
				(int)context_serial_getcmd(msg, len));
			/* and fall through to quit */
		case UB_LIBCMD_QUIT:
			free(msg);
			comm_base_exit(w->base);
			break;
		case UB_LIBCMD_NEWQUERY:
			handle_newq(w, msg, len);
			break;
		case UB_LIBCMD_CANCEL:
			handle_cancel(w, msg, len);
			break;
	}
}
Пример #2
0
/** stop the bg thread */
static void ub_stop_bg(struct ub_ctx* ctx)
{
	/* 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);
#ifndef UB_ON_WINDOWS
			if(waitpid(ctx->bg_pid, NULL, 0) == -1) {
				if(verbosity > 2)
					log_err("waitpid: %s", strerror(errno));
			}
#endif
		}
	}
	else {
		lock_basic_unlock(&ctx->cfglock);
	}
}
Пример #3
0
/** process answer from bg worker */
static int
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
                      ub_callback_t* cb, void** cbarg, int* err,
                      struct ub_result** res)
{
    struct ctx_query* q;
    if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) {
        log_err("error: bad data from bg worker %d",
                (int)context_serial_getcmd(msg, len));
        return 0;
    }

    lock_basic_lock(&ctx->cfglock);
    q = context_deserialize_answer(ctx, msg, len, err);
    if(!q) {
        lock_basic_unlock(&ctx->cfglock);
        /* probably simply the lookup that failed, i.e.
         * response returned before cancel was sent out, so noerror */
        return 1;
    }
    log_assert(q->async);

    /* grab cb while locked */
    if(q->cancelled) {
        *cb = NULL;
        *cbarg = NULL;
    } else {
        *cb = q->cb;
        *cbarg = q->cb_arg;
    }
    if(*err) {
        *res = NULL;
        ub_resolve_free(q->res);
    } else {
        /* parse the message, extract rcode, fill result */
        ldns_buffer* buf = ldns_buffer_new(q->msg_len);
        struct regional* region = regional_create();
        *res = q->res;
        (*res)->rcode = LDNS_RCODE_SERVFAIL;
        if(region && buf) {
            ldns_buffer_clear(buf);
            ldns_buffer_write(buf, q->msg, q->msg_len);
            ldns_buffer_flip(buf);
            libworker_enter_result(*res, buf, region,
                                   q->msg_security);
        }
        (*res)->answer_packet = q->msg;
        (*res)->answer_len = (int)q->msg_len;
        q->msg = NULL;
        ldns_buffer_free(buf);
        regional_destroy(region);
    }
    q->res = NULL;
    /* delete the q from list */
    (void)rbtree_delete(&ctx->queries, q->node.key);
    ctx->num_async--;
    context_query_delete(q);
    lock_basic_unlock(&ctx->cfglock);

    if(*cb) return 2;
    ub_resolve_free(*res);
    return 1;
}
Пример #4
0
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
}