Example #1
0
int
ub_wait(struct ub_ctx* ctx)
{
    int err;
    ub_callback_t cb;
    void* cbarg;
    struct ub_result* res;
    int r;
    uint8_t* msg;
    uint32_t len;
    /* this is basically the same loop as _process(), but with changes.
     * holds the rrpipe lock and waits with tube_wait */
    while(1) {
        lock_basic_lock(&ctx->rrpipe_lock);
        lock_basic_lock(&ctx->cfglock);
        if(ctx->num_async == 0) {
            lock_basic_unlock(&ctx->cfglock);
            lock_basic_unlock(&ctx->rrpipe_lock);
            break;
        }
        lock_basic_unlock(&ctx->cfglock);

        /* keep rrpipe locked, while
         * 	o waiting for pipe readable
         * 	o parsing message
         * 	o possibly decrementing num_async
         * do callback without lock
         */
        r = tube_wait(ctx->rr_pipe);
        if(r) {
            r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
            if(r == 0) {
                lock_basic_unlock(&ctx->rrpipe_lock);
                return UB_PIPE;
            }
            if(r == -1) {
                lock_basic_unlock(&ctx->rrpipe_lock);
                continue;
            }
            r = process_answer_detail(ctx, msg, len,
                                      &cb, &cbarg, &err, &res);
            lock_basic_unlock(&ctx->rrpipe_lock);
            free(msg);
            if(r == 0)
                return UB_PIPE;
            if(r == 2)
                (*cb)(cbarg, err, res);
        } else {
            lock_basic_unlock(&ctx->rrpipe_lock);
        }
    }
    return UB_NOERROR;
}
Example #2
0
void tube_handle_signal(int ATTR_UNUSED(fd), short ATTR_UNUSED(events), 
	void* arg)
{
	struct tube* tube = (struct tube*)arg;
	uint8_t* buf;
	uint32_t len = 0;
	verbose(VERB_ALGO, "tube handle_signal");
	while(tube_poll(tube)) {
		if(tube_read_msg(tube, &buf, &len, 1)) {
			fptr_ok(fptr_whitelist_tube_listen(tube->listen_cb));
			(*tube->listen_cb)(tube, buf, len, NETEVENT_NOERROR, 
				tube->listen_arg);
		}
	}
}
Example #3
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);
	}
}
Example #4
0
int
ub_process(struct ub_ctx* ctx)
{
    int r;
    uint8_t* msg;
    uint32_t len;
    while(1) {
        msg = NULL;
        lock_basic_lock(&ctx->rrpipe_lock);
        r = tube_read_msg(ctx->rr_pipe, &msg, &len, 1);
        lock_basic_unlock(&ctx->rrpipe_lock);
        if(r == 0)
            return UB_PIPE;
        else if(r == -1)
            break;
        if(!process_answer(ctx, msg, len)) {
            free(msg);
            return UB_PIPE;
        }
        free(msg);
    }
    return UB_NOERROR;
}
Example #5
0
void server_stats_obtain(struct worker* worker, struct worker* who,
	struct stats_info* s, int reset)
{
	uint8_t *reply = NULL;
	uint32_t len = 0;
	if(worker == who) {
		/* just fill it in */
		server_stats_compile(worker, s, reset);
		return;
	}
	/* communicate over tube */
	verbose(VERB_ALGO, "write stats cmd");
	if(reset)
		worker_send_cmd(who, worker_cmd_stats);
	else 	worker_send_cmd(who, worker_cmd_stats_noreset);
	verbose(VERB_ALGO, "wait for stats reply");
	if(!tube_read_msg(worker->cmd, &reply, &len, 0))
		fatal_exit("failed to read stats over cmd channel");
	if(len != (uint32_t)sizeof(*s))
		fatal_exit("stats on cmd channel wrong length %d %d",
			(int)len, (int)sizeof(*s));
	memcpy(s, reply, (size_t)len);
	free(reply);
}
Example #6
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
}