/** the background thread func */ static void* libworker_dobg(void* arg) { /* setup */ uint32_t m; struct libworker* w = (struct libworker*)arg; struct ub_ctx* ctx; if(!w) { log_err("libunbound bg worker init failed, nomem"); return NULL; } ctx = w->ctx; log_thread_set(&w->thread_num); #ifdef THREADS_DISABLED /* we are forked */ w->is_bg_thread = 0; /* close non-used parts of the pipes */ tube_close_write(ctx->qq_pipe); tube_close_read(ctx->rr_pipe); #endif if(!tube_setup_bg_listen(ctx->qq_pipe, w->base, libworker_handle_control_cmd, w)) { log_err("libunbound bg worker init failed, no bglisten"); return NULL; } if(!tube_setup_bg_write(ctx->rr_pipe, w->base)) { log_err("libunbound bg worker init failed, no bgwrite"); return NULL; } /* do the work */ comm_base_dispatch(w->base); /* cleanup */ m = UB_LIBCMD_QUIT; w->want_quit = 1; tube_remove_bg_listen(w->ctx->qq_pipe); tube_remove_bg_write(w->ctx->rr_pipe); libworker_delete(w); (void)tube_write_msg(ctx->rr_pipe, (uint8_t*)&m, (uint32_t)sizeof(m), 0); #ifdef THREADS_DISABLED /* close pipes from forked process before exit */ tube_close_read(ctx->qq_pipe); tube_close_write(ctx->rr_pipe); #endif return NULL; }
/** * Function to start one thread. * @param arg: user argument. * @return: void* user return value could be used for thread_join results. */ static void* thread_start(void* arg) { struct worker* worker = (struct worker*)arg; int port_num = 0; log_thread_set(&worker->thread_num); ub_thread_blocksigs(); #ifdef THREADS_DISABLED /* close pipe ends used by main */ tube_close_write(worker->cmd); close_other_pipes(worker->daemon, worker->thread_num); #endif #ifdef SO_REUSEPORT if(worker->daemon->cfg->so_reuseport) port_num = worker->thread_num % worker->daemon->num_ports; else port_num = 0; #endif if(!worker_init(worker, worker->daemon->cfg, worker->daemon->ports[port_num], 0)) fatal_exit("Could not initialize thread"); worker_work(worker); return NULL; }
int libworker_bg(struct ub_ctx* ctx) { struct libworker* w; /* fork or threadcreate */ lock_basic_lock(&ctx->cfglock); if(ctx->dothread) { lock_basic_unlock(&ctx->cfglock); w = libworker_setup(ctx, 1, NULL); if(!w) return UB_NOMEM; w->is_bg_thread = 1; #ifdef ENABLE_LOCK_CHECKS w->thread_num = 1; /* for nicer DEBUG checklocks */ #endif ub_thread_create(&ctx->bg_tid, libworker_dobg, w); } else { lock_basic_unlock(&ctx->cfglock); #ifndef HAVE_FORK /* no fork on windows */ return UB_FORKFAIL; #else /* HAVE_FORK */ switch((ctx->bg_pid=fork())) { case 0: w = libworker_setup(ctx, 1, NULL); if(!w) fatal_exit("out of memory"); /* close non-used parts of the pipes */ tube_close_write(ctx->qq_pipe); tube_close_read(ctx->rr_pipe); (void)libworker_dobg(w); exit(0); break; case -1: return UB_FORKFAIL; default: /* close non-used parts, so that the worker * bgprocess gets 'pipe closed' when the * main process exits */ tube_close_read(ctx->qq_pipe); tube_close_write(ctx->rr_pipe); break; } #endif /* HAVE_FORK */ } return UB_NOERROR; }
void tube_delete(struct tube* tube) { if(!tube) return; tube_remove_bg_listen(tube); tube_remove_bg_write(tube); /* close fds after deleting commpoints, to be sure. * Also epoll does not like closing fd before event_del */ tube_close_read(tube); tube_close_write(tube); free(tube); }
void tube_delete(struct tube* tube) { if(!tube) return; tube_remove_bg_listen(tube); tube_remove_bg_write(tube); tube_close_read(tube); tube_close_write(tube); if(!WSACloseEvent(tube->event)) log_err("WSACloseEvent: %s", wsa_strerror(WSAGetLastError())); lock_basic_destroy(&tube->res_lock); verbose(VERB_ALGO, "tube deleted"); free(tube); }