isc_result_t isc_app_onrun(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; LOCK(&lock); if (running) { result = ISC_R_ALREADYRUNNING; goto unlock; } /* * 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) { result = ISC_R_NOMEMORY; goto unlock; } ISC_LIST_APPEND(on_run, event, ev_link); result = ISC_R_SUCCESS; unlock: UNLOCK(&lock); return (result); }
ATF_TC_BODY(get_objects, tc) { isc_result_t result; isc_pool_t *pool = NULL; void *item; isc_task_t *task1 = NULL, *task2 = NULL, *task3 = NULL; UNUSED(tc); result = isc_test_begin(NULL, ISC_TRUE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = isc_pool_create(mctx, 2, poolfree, poolinit, taskmgr, &pool); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(isc_pool_count(pool), 2); item = isc_pool_get(pool); ATF_REQUIRE(item != NULL); isc_task_attach((isc_task_t *) item, &task1); item = isc_pool_get(pool); ATF_REQUIRE(item != NULL); isc_task_attach((isc_task_t *) item, &task2); item = isc_pool_get(pool); ATF_REQUIRE(item != NULL); isc_task_attach((isc_task_t *) item, &task3); isc_task_detach(&task1); isc_task_detach(&task2); isc_task_detach(&task3); isc_pool_destroy(&pool); ATF_REQUIRE_EQ(pool, NULL); isc_test_end(); }
isc_result_t isc_ondestroy_register(isc_ondestroy_t *ondest, isc_task_t *task, isc_event_t **eventp) { isc_event_t *theevent; isc_task_t *thetask = NULL; REQUIRE(VALID_ONDESTROY(ondest)); REQUIRE(task != NULL); REQUIRE(eventp != NULL); theevent = *eventp; REQUIRE(theevent != NULL); isc_task_attach(task, &thetask); theevent->ev_sender = thetask; ISC_LIST_APPEND(ondest->events, theevent, ev_link); return (ISC_R_SUCCESS); }
isc_result_t isc_httpdmgr_create(isc_mem_t *mctx, isc_socket_t *sock, isc_task_t *task, isc_httpdclientok_t *client_ok, isc_httpdondestroy_t *ondestroy, void *cb_arg, isc_timermgr_t *tmgr, isc_httpdmgr_t **httpdp) { isc_result_t result; isc_httpdmgr_t *httpd; REQUIRE(mctx != NULL); REQUIRE(sock != NULL); REQUIRE(task != NULL); REQUIRE(tmgr != NULL); REQUIRE(httpdp != NULL && *httpdp == NULL); httpd = isc_mem_get(mctx, sizeof(isc_httpdmgr_t)); if (httpd == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&httpd->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t)); return (result); } httpd->mctx = NULL; isc_mem_attach(mctx, &httpd->mctx); httpd->sock = NULL; isc_socket_attach(sock, &httpd->sock); httpd->task = NULL; isc_task_attach(task, &httpd->task); httpd->timermgr = tmgr; /* XXXMLG no attach function? */ httpd->client_ok = client_ok; httpd->ondestroy = ondestroy; httpd->cb_arg = cb_arg; ISC_LIST_INIT(httpd->running); ISC_LIST_INIT(httpd->urls); /* XXXMLG ignore errors on isc_socket_listen() */ result = isc_socket_listen(sock, SOMAXCONN); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_socket_listen() failed: %s", isc_result_totext(result)); goto cleanup; } (void)isc_socket_filter(sock, "httpready"); result = isc_socket_accept(sock, task, isc_httpd_accept, httpd); if (result != ISC_R_SUCCESS) goto cleanup; httpd->render_404 = render_404; httpd->render_500 = render_500; *httpdp = httpd; return (ISC_R_SUCCESS); cleanup: isc_task_detach(&httpd->task); isc_socket_detach(&httpd->sock); isc_mem_detach(&httpd->mctx); (void)isc_mutex_destroy(&httpd->lock); isc_mem_put(mctx, httpd, sizeof(isc_httpdmgr_t)); return (result); }
ISC_TIMERFUNC_SCOPE isc_result_t isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, isc_time_t *expires, isc_interval_t *interval, isc_task_t *task, isc_taskaction_t action, const void *arg, isc_timer_t **timerp) { isc__timermgr_t *manager = (isc__timermgr_t *)manager0; isc__timer_t *timer; isc_result_t result; isc_time_t now; /* * Create a new 'type' timer managed by 'manager'. The timers * parameters are specified by 'expires' and 'interval'. Events * will be posted to 'task' and when dispatched 'action' will be * called with 'arg' as the arg value. The new timer is returned * in 'timerp'. */ REQUIRE(VALID_MANAGER(manager)); REQUIRE(task != NULL); REQUIRE(action != NULL); if (expires == NULL) expires = isc_time_epoch; if (interval == NULL) interval = isc_interval_zero; REQUIRE(type == isc_timertype_inactive || !(isc_time_isepoch(expires) && isc_interval_iszero(interval))); REQUIRE(timerp != NULL && *timerp == NULL); REQUIRE(type != isc_timertype_limited || !(isc_time_isepoch(expires) || isc_interval_iszero(interval))); /* * Get current time. */ if (type != isc_timertype_inactive) { TIME_NOW(&now); } else { /* * We don't have to do this, but it keeps the compiler from * complaining about "now" possibly being used without being * set, even though it will never actually happen. */ isc_time_settoepoch(&now); } timer = isc_mem_get(manager->mctx, sizeof(*timer)); if (timer == NULL) return (ISC_R_NOMEMORY); timer->manager = manager; timer->references = 1; if (type == isc_timertype_once && !isc_interval_iszero(interval)) { result = isc_time_add(&now, interval, &timer->idle); if (result != ISC_R_SUCCESS) { isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } } else isc_time_settoepoch(&timer->idle); timer->type = type; timer->expires = *expires; timer->interval = *interval; timer->task = NULL; isc_task_attach(task, &timer->task); timer->action = action; /* * Removing the const attribute from "arg" is the best of two * evils here. If the timer->arg member is made const, then * it affects a great many recipients of the timer event * which did not pass in an "arg" that was truly const. * Changing isc_timer_create() to not have "arg" prototyped as const, * though, can cause compilers warnings for calls that *do* * have a truly const arg. The caller will have to carefully * keep track of whether arg started as a true const. */ DE_CONST(arg, timer->arg); timer->index = 0; result = isc_mutex_init(&timer->lock); if (result != ISC_R_SUCCESS) { isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } ISC_LINK_INIT(timer, link); timer->common.impmagic = TIMER_MAGIC; timer->common.magic = ISCAPI_TIMER_MAGIC; timer->common.methods = (isc_timermethods_t *)&timermethods; LOCK(&manager->lock); /* * Note we don't have to lock the timer like we normally would because * there are no external references to it yet. */ if (type != isc_timertype_inactive) result = schedule(timer, &now, ISC_TRUE); else result = ISC_R_SUCCESS; if (result == ISC_R_SUCCESS) APPEND(manager->timers, timer, link); UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { timer->common.impmagic = 0; timer->common.magic = 0; DESTROYLOCK(&timer->lock); isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } *timerp = (isc_timer_t *)timer; return (ISC_R_SUCCESS); }
isc_result_t ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, isc_socketmgr_t *socketmgr, dns_dispatchmgr_t *dispatchmgr, isc_task_t *task, ns_interfacemgr_t **mgrp) { isc_result_t result; ns_interfacemgr_t *mgr; #ifndef USE_ROUTE_SOCKET UNUSED(task); #endif REQUIRE(mctx != NULL); REQUIRE(mgrp != NULL); REQUIRE(*mgrp == NULL); mgr = isc_mem_get(mctx, sizeof(*mgr)); if (mgr == NULL) return (ISC_R_NOMEMORY); mgr->mctx = NULL; isc_mem_attach(mctx, &mgr->mctx); result = isc_mutex_init(&mgr->lock); if (result != ISC_R_SUCCESS) goto cleanup_mem; mgr->taskmgr = taskmgr; mgr->socketmgr = socketmgr; mgr->dispatchmgr = dispatchmgr; mgr->generation = 1; mgr->listenon4 = NULL; mgr->listenon6 = NULL; ISC_LIST_INIT(mgr->interfaces); ISC_LIST_INIT(mgr->listenon); /* * The listen-on lists are initially empty. */ result = ns_listenlist_create(mctx, &mgr->listenon4); if (result != ISC_R_SUCCESS) goto cleanup_mem; ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); result = dns_aclenv_init(mctx, &mgr->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_listenon; #ifdef HAVE_GEOIP mgr->aclenv.geoip = ns_g_geoip; #endif #ifdef USE_ROUTE_SOCKET mgr->route = NULL; result = isc_socket_create(mgr->socketmgr, ROUTE_SOCKET_PROTOCOL, isc_sockettype_raw, &mgr->route); switch (result) { case ISC_R_NOPERM: case ISC_R_SUCCESS: case ISC_R_NOTIMPLEMENTED: case ISC_R_FAMILYNOSUPPORT: break; default: goto cleanup_aclenv; } mgr->task = NULL; if (mgr->route != NULL) isc_task_attach(task, &mgr->task); mgr->references = (mgr->route != NULL) ? 2 : 1; #else mgr->references = 1; #endif mgr->magic = IFMGR_MAGIC; *mgrp = mgr; #ifdef USE_ROUTE_SOCKET if (mgr->route != NULL) { isc_region_t r = { mgr->buf, sizeof(mgr->buf) }; result = isc_socket_recv(mgr->route, &r, 1, mgr->task, route_event, mgr); if (result != ISC_R_SUCCESS) { isc_task_detach(&mgr->task); isc_socket_detach(&mgr->route); ns_interfacemgr_detach(&mgr); } } #endif return (ISC_R_SUCCESS); #ifdef USE_ROUTE_SOCKET cleanup_aclenv: dns_aclenv_destroy(&mgr->aclenv); #endif cleanup_listenon: ns_listenlist_detach(&mgr->listenon4); ns_listenlist_detach(&mgr->listenon6); cleanup_mem: isc_mem_putanddetach(&mgr->mctx, mgr, sizeof(*mgr)); return (result); }
void isc_taskpool_gettask(isc_taskpool_t *pool, unsigned int hash, isc_task_t **targetp) { isc_task_attach(pool->tasks[hash % pool->ntasks], targetp); }
isc_result_t dns_lookup_create(isc_mem_t *mctx, dns_name_t *name, dns_rdatatype_t type, dns_view_t *view, unsigned int options, isc_task_t *task, isc_taskaction_t action, void *arg, dns_lookup_t **lookupp) { isc_result_t result; dns_lookup_t *lookup; isc_event_t *ievent; lookup = isc_mem_get(mctx, sizeof(*lookup)); if (lookup == NULL) return (ISC_R_NOMEMORY); lookup->mctx = NULL; isc_mem_attach(mctx, &lookup->mctx); lookup->options = options; ievent = isc_event_allocate(mctx, lookup, DNS_EVENT_LOOKUPDONE, action, arg, sizeof(*lookup->event)); if (ievent == NULL) { result = ISC_R_NOMEMORY; goto cleanup_lookup; } lookup->event = (dns_lookupevent_t *)ievent; lookup->event->ev_destroy = levent_destroy; lookup->event->ev_destroy_arg = mctx; lookup->event->result = ISC_R_FAILURE; lookup->event->name = NULL; lookup->event->rdataset = NULL; lookup->event->sigrdataset = NULL; lookup->event->db = NULL; lookup->event->node = NULL; lookup->task = NULL; isc_task_attach(task, &lookup->task); result = isc_mutex_init(&lookup->lock); if (result != ISC_R_SUCCESS) goto cleanup_event; dns_fixedname_init(&lookup->name); result = dns_name_copy(name, dns_fixedname_name(&lookup->name), NULL); if (result != ISC_R_SUCCESS) goto cleanup_lock; lookup->type = type; lookup->view = NULL; dns_view_attach(view, &lookup->view); lookup->fetch = NULL; lookup->restarts = 0; lookup->canceled = ISC_FALSE; dns_rdataset_init(&lookup->rdataset); dns_rdataset_init(&lookup->sigrdataset); lookup->magic = LOOKUP_MAGIC; *lookupp = lookup; lookup_find(lookup, NULL); return (ISC_R_SUCCESS); cleanup_lock: DESTROYLOCK(&lookup->lock); cleanup_event: ievent = (isc_event_t *)lookup->event; isc_event_free(&ievent); lookup->event = NULL; isc_task_detach(&lookup->task); cleanup_lookup: isc_mem_putanddetach(&mctx, lookup, sizeof(*lookup)); return (result); }
void isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) { isc_uint32_t i; isc_random_get(&i); isc_task_attach(pool->tasks[i % pool->ntasks], targetp); }
int main(int argc, char *argv[]) { unsigned int workers; t_info *t1, *t2; isc_task_t *task; isc_mem_t *mctx, *mctx2; RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS); if (argc > 1) workers = atoi(argv[1]); else workers = 2; printf("%d workers\n", workers); mctx = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); mctx2 = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx2) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &task_manager) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_timermgr_create(mctx, &timer_manager) == ISC_R_SUCCESS); t1 = new_task(mctx, NULL); t2 = new_task(mctx2, NULL); isc_task_attach(t2->task, &t1->peer); isc_task_attach(t1->task, &t2->peer); /* * Test run-triggered shutdown. */ (void)new_task(mctx2, "foo"); /* * Test implicit shutdown. */ task = NULL; RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) == ISC_R_SUCCESS); isc_task_detach(&task); /* * Test anti-zombie code. */ RUNTIME_CHECK(isc_task_create(task_manager, 0, &task) == ISC_R_SUCCESS); isc_task_detach(&task); RUNTIME_CHECK(isc_app_run() == ISC_R_SUCCESS); isc_taskmgr_destroy(&task_manager); isc_timermgr_destroy(&timer_manager); printf("Statistics for mctx:\n"); isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); printf("Statistics for mctx2:\n"); isc_mem_stats(mctx2, stdout); isc_mem_destroy(&mctx2); isc_app_finish(); return (0); }