diff --git a/CHANGES b/CHANGES index af1a85a5a9..3a4fe31a5f 100644 --- a/CHANGES +++ b/CHANGES @@ -17,9 +17,10 @@ 1581. [func] Disable DNSSEC support by default. To enable DNSSEC specify "enable-dnssec yes;" in named.conf. -1580. [placeholder] rt3746a +1580. [bug] Zone destuction on final detach takes a long time. + [RT #3746] -1579. [placeholder] rt3746a +1579. [bug] Multiple task managers could not be created. 1578. [bug] Don't use CLASS E IPv4 addresses when resolving. [RT #10346] diff --git a/lib/dns/db.c b/lib/dns/db.c index c1203c6d84..8814dd710f 100644 --- a/lib/dns/db.c +++ b/lib/dns/db.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.c,v 1.72 2003/10/03 03:12:35 marka Exp $ */ +/* $Id: db.c,v 1.73 2004/03/04 06:56:38 marka Exp $ */ /*** *** Imports @@ -730,6 +730,13 @@ dns_db_nodecount(dns_db_t *db) { return ((db->methods->nodecount)(db)); } +void +dns_db_settask(dns_db_t *db, isc_task_t *task) { + REQUIRE(DNS_DB_VALID(db)); + + (db->methods->settask)(db, task); +} + isc_result_t dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg, isc_mem_t *mctx, dns_dbimplementation_t **dbimp) diff --git a/lib/dns/include/dns/db.h b/lib/dns/include/dns/db.h index 975e2a0031..04ef341f78 100644 --- a/lib/dns/include/dns/db.h +++ b/lib/dns/include/dns/db.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: db.h,v 1.74 2003/10/03 03:12:35 marka Exp $ */ +/* $Id: db.h,v 1.75 2004/03/04 06:56:40 marka Exp $ */ #ifndef DNS_DB_H #define DNS_DB_H 1 @@ -144,6 +144,7 @@ typedef struct dns_dbmethods { unsigned int (*nodecount)(dns_db_t *db); isc_boolean_t (*ispersistent)(dns_db_t *db); void (*overmem)(dns_db_t *db, isc_boolean_t overmem); + void (*settask)(dns_db_t *db, isc_task_t *); } dns_dbmethods_t; typedef isc_result_t @@ -1189,6 +1190,16 @@ dns_db_nodecount(dns_db_t *db); * The number of nodes in the database */ +void +dns_db_settask(dns_db_t *db, isc_task_t *task); +/* + * If task is set then the final detach maybe performed asynchronously. + * + * Requires: + * 'db' is a valid database. + * 'task' to be valid or NULL. + */ + isc_boolean_t dns_db_ispersistent(dns_db_t *db); /* diff --git a/lib/dns/include/dns/events.h b/lib/dns/include/dns/events.h index d44dbd2f45..b048f2697d 100644 --- a/lib/dns/include/dns/events.h +++ b/lib/dns/include/dns/events.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: events.h,v 1.40 2002/09/04 02:26:13 jinmei Exp $ */ +/* $Id: events.h,v 1.41 2004/03/04 06:56:40 marka Exp $ */ #ifndef DNS_EVENTS_H #define DNS_EVENTS_H 1 @@ -62,6 +62,7 @@ #define DNS_EVENT_REQUESTCONTROL (ISC_EVENTCLASS_DNS + 33) #define DNS_EVENT_DUMPQUANTUM (ISC_EVENTCLASS_DNS + 34) #define DNS_EVENT_IMPORTRECVDONE (ISC_EVENTCLASS_DNS + 35) +#define DNS_EVENT_FREESTORAGE (ISC_EVENTCLASS_DNS + 36) #define DNS_EVENT_FIRSTEVENT (ISC_EVENTCLASS_DNS + 0) #define DNS_EVENT_LASTEVENT (ISC_EVENTCLASS_DNS + 65535) diff --git a/lib/dns/include/dns/rbt.h b/lib/dns/include/dns/rbt.h index 0d49eaa6e1..d82586f40b 100644 --- a/lib/dns/include/dns/rbt.h +++ b/lib/dns/include/dns/rbt.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.h,v 1.57 2002/12/31 05:40:15 marka Exp $ */ +/* $Id: rbt.h,v 1.58 2004/03/04 06:56:40 marka Exp $ */ #ifndef DNS_RBT_H #define DNS_RBT_H 1 @@ -600,8 +600,13 @@ dns_rbt_nodecount(dns_rbt_t *rbt); void dns_rbt_destroy(dns_rbt_t **rbtp); +isc_result_t +dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum); /* - * Stop working with a red-black tree of trees. + * Stop working with a red-black tree of trees. Once dns_rbt_destroy2() + * has been called on a 'rbt' only dns_rbt_destroy() or dns_rbt_destroy2() + * may be used on the tree. If 'quantum' is zero then the entire tree will + * be destroyed. * * Requires: * *rbt is a valid rbt manager. @@ -610,6 +615,10 @@ dns_rbt_destroy(dns_rbt_t **rbtp); * All space allocated by the RBT library has been returned. * * *rbt is invalidated as an rbt manager. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_QUOTA if 'quantum' nodes have been destroyed. */ void diff --git a/lib/dns/rbt.c b/lib/dns/rbt.c index 1094fdf6ee..c557a64200 100644 --- a/lib/dns/rbt.c +++ b/lib/dns/rbt.c @@ -15,13 +15,14 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbt.c,v 1.126 2004/03/03 22:40:56 marka Exp $ */ +/* $Id: rbt.c,v 1.127 2004/03/04 06:56:39 marka Exp $ */ /* Principal Authors: DCL */ #include #include +#include #include #include #include @@ -63,6 +64,7 @@ struct dns_rbt { unsigned int nodecount; unsigned int hashsize; dns_rbtnode_t ** hashtable; + unsigned int quantum; }; #define RED 0 @@ -225,9 +227,12 @@ dns_rbt_addonlevel(dns_rbtnode_t *node, dns_rbtnode_t *current, int order, static void dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp); -static void +static isc_result_t dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node); +static void +dns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep); + /* * Initialize a red/black tree of trees. */ @@ -263,6 +268,7 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *), return (result); } #endif + rbt->quantum = 0; rbt->magic = RBT_MAGIC; *rbtp = rbt; @@ -275,13 +281,22 @@ dns_rbt_create(isc_mem_t *mctx, void (*deleter)(void *, void *), */ void dns_rbt_destroy(dns_rbt_t **rbtp) { + RUNTIME_CHECK(dns_rbt_destroy2(rbtp, 0) == ISC_R_SUCCESS); +} + +isc_result_t +dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) { dns_rbt_t *rbt; REQUIRE(rbtp != NULL && VALID_RBT(*rbtp)); rbt = *rbtp; - dns_rbt_deletetree(rbt, rbt->root); + rbt->quantum = quantum; + + dns_rbt_deletetreeflat(rbt, &rbt->root); + if (rbt->root != NULL) + return (ISC_R_QUOTA); INSIST(rbt->nodecount == 0); @@ -292,8 +307,8 @@ dns_rbt_destroy(dns_rbt_t **rbtp) { rbt->magic = 0; isc_mem_put(rbt->mctx, rbt, sizeof(*rbt)); - *rbtp = NULL; + return (ISC_R_SUCCESS); } unsigned int @@ -1258,7 +1273,8 @@ dns_rbt_deletenode(dns_rbt_t *rbt, dns_rbtnode_t *node, isc_boolean_t recurse) if (DOWN(node) != NULL) { if (recurse) - dns_rbt_deletetree(rbt, DOWN(node)); + RUNTIME_CHECK(dns_rbt_deletetree(rbt, DOWN(node)) + == ISC_R_SUCCESS); else { if (DATA(node) != NULL && rbt->data_deleter != NULL) rbt->data_deleter(DATA(node), @@ -1527,7 +1543,7 @@ hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) { REQUIRE(DNS_RBTNODE_VALID(node)); - if (rbt->nodecount >= rbt->hashsize) + if (rbt->nodecount >= (rbt->hashsize *3)) rehash(rbt); hash_add_node(rbt, node); @@ -1976,19 +1992,37 @@ dns_rbt_deletefromlevel(dns_rbtnode_t *delete, dns_rbtnode_t **rootp) { * a pointer needs to be told that this tree no longer exists, * this function would need to adjusted accordingly. */ -static void +static isc_result_t dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) { + isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_RBT(rbt)); if (node == NULL) - return; + return (result); - if (LEFT(node) != NULL) - dns_rbt_deletetree(rbt, LEFT(node)); - if (RIGHT(node) != NULL) - dns_rbt_deletetree(rbt, RIGHT(node)); - if (DOWN(node) != NULL) - dns_rbt_deletetree(rbt, DOWN(node)); + if (LEFT(node) != NULL) { + result = dns_rbt_deletetree(rbt, LEFT(node)); + if (result != ISC_R_SUCCESS) + goto done; + LEFT(node) = NULL; + } + if (RIGHT(node) != NULL) { + result = dns_rbt_deletetree(rbt, RIGHT(node)); + if (result != ISC_R_SUCCESS) + goto done; + RIGHT(node) = NULL; + } + if (DOWN(node) != NULL) { + result = dns_rbt_deletetree(rbt, DOWN(node)); + if (result != ISC_R_SUCCESS) + goto done; + DOWN(node) = NULL; + } + done: + if (result != ISC_R_SUCCESS) + return (result); + if (rbt->quantum != 0 && --rbt->quantum == 0) + return (ISC_R_QUOTA); if (DATA(node) != NULL && rbt->data_deleter != NULL) rbt->data_deleter(DATA(node), rbt->deleter_arg); @@ -1999,6 +2033,59 @@ dns_rbt_deletetree(dns_rbt_t *rbt, dns_rbtnode_t *node) { #endif isc_mem_put(rbt->mctx, node, NODE_SIZE(node)); rbt->nodecount--; + return (result); +} + +static void +dns_rbt_deletetreeflat(dns_rbt_t *rbt, dns_rbtnode_t **nodep) { + dns_rbtnode_t *parent; + dns_rbtnode_t *node = *nodep; + REQUIRE(VALID_RBT(rbt)); + + again: + if (node == NULL) { + *nodep = NULL; + return; + } + + traverse: + if (LEFT(node) != NULL) { + node = LEFT(node); + goto traverse; + } + if (RIGHT(node) != NULL) { + node = RIGHT(node); + goto traverse; + } + if (DOWN(node) != NULL) { + node = DOWN(node); + goto traverse; + } + + if (DATA(node) != NULL && rbt->data_deleter != NULL) + rbt->data_deleter(DATA(node), rbt->deleter_arg); + + unhash_node(rbt, node); +#if DNS_RBT_USEMAGIC + node->magic = 0; +#endif + parent = PARENT(node); + if (parent != NULL) { + if (LEFT(parent) == node) + LEFT(parent) = NULL; + else if (DOWN(parent) == node) + DOWN(parent) = NULL; + else if (RIGHT(parent) == node) + RIGHT(parent) = NULL; + } + isc_mem_put(rbt->mctx, node, NODE_SIZE(node)); + rbt->nodecount--; + node = parent; + if (rbt->quantum != 0 && --rbt->quantum == 0) { + *nodep = node; + return; + } + goto again; } static void diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 9cc1a35d34..9f812741a9 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: rbtdb.c,v 1.194 2004/03/04 02:46:28 marka Exp $ */ +/* $Id: rbtdb.c,v 1.195 2004/03/04 06:56:39 marka Exp $ */ /* * Principal Author: Bob Halley @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -30,10 +31,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -215,6 +218,7 @@ typedef struct { rbtdb_version_t * future_version; rbtdb_versionlist_t open_versions; isc_boolean_t overmem; + isc_task_t * task; /* Locked by tree_lock. */ dns_rbt_t * tree; isc_boolean_t secure; @@ -339,6 +343,9 @@ typedef struct rbtdb_dbiterator { #define IS_STUB(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_STUB) != 0) #define IS_CACHE(rbtdb) (((rbtdb)->common.attributes & DNS_DBATTR_CACHE) != 0) +static void free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, + isc_event_t *event); + /* * Locking * @@ -382,10 +389,20 @@ attach(dns_db_t *source, dns_db_t **targetp) { } static void -free_rbtdb(dns_rbtdb_t *rbtdb) { +free_rbtdb_callback(isc_task_t *task, isc_event_t *event) { + dns_rbtdb_t *rbtdb = event->ev_arg; + + UNUSED(task); + + free_rbtdb(rbtdb, ISC_TRUE, event); +} + +static void +free_rbtdb(dns_rbtdb_t *rbtdb, isc_boolean_t log, isc_event_t *event) { unsigned int i; isc_ondestroy_t ondest; - isc_mem_t *mctx; + isc_result_t result; + char buf[DNS_NAME_FORMATSIZE]; REQUIRE(EMPTY(rbtdb->open_versions)); REQUIRE(rbtdb->future_version == NULL); @@ -393,23 +410,53 @@ free_rbtdb(dns_rbtdb_t *rbtdb) { if (rbtdb->current_version != NULL) isc_mem_put(rbtdb->common.mctx, rbtdb->current_version, sizeof(rbtdb_version_t)); + again: + if (rbtdb->tree != NULL) { + result = dns_rbt_destroy2(&rbtdb->tree, + (rbtdb->task != NULL) ? 5 : 0); + if (result == ISC_R_QUOTA) { + INSIST(rbtdb->task != NULL); + if (event == NULL) + event = isc_event_allocate(rbtdb->common.mctx, + NULL, + DNS_EVENT_FREESTORAGE, + free_rbtdb_callback, + rbtdb, + sizeof(isc_event_t)); + if (event == NULL) + goto again; + isc_task_send(rbtdb->task, &event); + return; + } + INSIST(result == ISC_R_SUCCESS && rbtdb->tree == NULL); + } + if (event != NULL) + isc_event_free(&event); + if (log) { + if (dns_name_dynamic(&rbtdb->common.origin)) + dns_name_format(&rbtdb->common.origin, buf, + sizeof(buf)); + else + strcpy(buf, ""); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1), + "done free_rbtdb(%s)", buf); + } if (dns_name_dynamic(&rbtdb->common.origin)) dns_name_free(&rbtdb->common.origin, rbtdb->common.mctx); - if (rbtdb->tree != NULL) - dns_rbt_destroy(&rbtdb->tree); for (i = 0; i < rbtdb->node_lock_count; i++) DESTROYLOCK(&rbtdb->node_locks[i].lock); isc_mem_put(rbtdb->common.mctx, rbtdb->node_locks, rbtdb->node_lock_count * sizeof(rbtdb_nodelock_t)); isc_rwlock_destroy(&rbtdb->tree_lock); isc_refcount_destroy(&rbtdb->references); + if (rbtdb->task != NULL) + isc_task_detach(&rbtdb->task); DESTROYLOCK(&rbtdb->lock); rbtdb->common.magic = 0; rbtdb->common.impmagic = 0; ondest = rbtdb->common.ondest; - mctx = rbtdb->common.mctx; - isc_mem_put(mctx, rbtdb, sizeof(*rbtdb)); - isc_mem_detach(&mctx); + isc_mem_putanddetach(&rbtdb->common.mctx, rbtdb, sizeof(*rbtdb)); isc_ondestroy_notify(&ondest, rbtdb); } @@ -439,8 +486,18 @@ maybe_free_rbtdb(dns_rbtdb_t *rbtdb) { if (rbtdb->active == 0) want_free = ISC_TRUE; UNLOCK(&rbtdb->lock); - if (want_free) - free_rbtdb(rbtdb); + if (want_free) { + char buf[DNS_NAME_FORMATSIZE]; + if (dns_name_dynamic(&rbtdb->common.origin)) + dns_name_format(&rbtdb->common.origin, buf, + sizeof(buf)); + else + strcpy(buf, ""); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1), + "calling free_rbtdb(%s)", buf); + free_rbtdb(rbtdb, ISC_TRUE, NULL); + } } } @@ -3166,8 +3223,18 @@ detachnode(dns_db_t *db, dns_dbnode_t **targetp) { if (rbtdb->active == 0) want_free = ISC_TRUE; UNLOCK(&rbtdb->lock); - if (want_free) - free_rbtdb(rbtdb); + if (want_free) { + char buf[DNS_NAME_FORMATSIZE]; + if (dns_name_dynamic(&rbtdb->common.origin)) + dns_name_format(&rbtdb->common.origin, buf, + sizeof(buf)); + else + strcpy(buf, ""); + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, + DNS_LOGMODULE_CACHE, ISC_LOG_DEBUG(1), + "calling free_rbtdb(%s)", buf); + free_rbtdb(rbtdb, ISC_TRUE, NULL); + } } } @@ -4552,6 +4619,22 @@ nodecount(dns_db_t *db) { return (count); } +static void +settask(dns_db_t *db, isc_task_t *task) { + dns_rbtdb_t *rbtdb; + + rbtdb = (dns_rbtdb_t *)db; + + REQUIRE(VALID_RBTDB(rbtdb)); + + LOCK(&rbtdb->lock); + if (rbtdb->task != NULL) + isc_task_detach(&rbtdb->task); + if (task != NULL) + isc_task_attach(task, &rbtdb->task); + UNLOCK(&rbtdb->lock); +} + static isc_boolean_t ispersistent(dns_db_t *db) { UNUSED(db); @@ -4584,7 +4667,8 @@ static dns_dbmethods_t zone_methods = { issecure, nodecount, ispersistent, - overmem + overmem, + settask }; static dns_dbmethods_t cache_methods = { @@ -4613,7 +4697,8 @@ static dns_dbmethods_t cache_methods = { issecure, nodecount, ispersistent, - overmem + overmem, + settask }; isc_result_t @@ -4714,7 +4799,7 @@ dns_rbtdb_create */ result = dns_name_dupwithoffsets(origin, mctx, &rbtdb->common.origin); if (result != ISC_R_SUCCESS) { - free_rbtdb(rbtdb); + free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } @@ -4723,7 +4808,7 @@ dns_rbtdb_create */ result = dns_rbt_create(mctx, delete_callback, rbtdb, &rbtdb->tree); if (result != ISC_R_SUCCESS) { - free_rbtdb(rbtdb); + free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } /* @@ -4745,7 +4830,7 @@ dns_rbtdb_create &rbtdb->origin_node); if (result != ISC_R_SUCCESS) { INSIST(result != ISC_R_EXISTS); - free_rbtdb(rbtdb); + free_rbtdb(rbtdb, ISC_FALSE, NULL); return (result); } /* @@ -4771,6 +4856,7 @@ dns_rbtdb_create rbtdb->attributes = 0; rbtdb->secure = ISC_FALSE; rbtdb->overmem = ISC_FALSE; + rbtdb->task = NULL; /* * Version Initialization. @@ -4780,7 +4866,7 @@ dns_rbtdb_create rbtdb->next_serial = 2; rbtdb->current_version = allocate_version(mctx, 1, 0, ISC_FALSE); if (rbtdb->current_version == NULL) { - free_rbtdb(rbtdb); + free_rbtdb(rbtdb, ISC_FALSE, NULL); return (ISC_R_NOMEMORY); } rbtdb->future_version = NULL; diff --git a/lib/dns/sdb.c b/lib/dns/sdb.c index 60c048cc18..6ebe385079 100644 --- a/lib/dns/sdb.c +++ b/lib/dns/sdb.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: sdb.c,v 1.43 2004/02/27 20:41:44 marka Exp $ */ +/* $Id: sdb.c,v 1.44 2004/03/04 06:56:39 marka Exp $ */ #include @@ -1200,6 +1200,12 @@ overmem(dns_db_t *db, isc_boolean_t overmem) { UNUSED(overmem); } +static void +settask(dns_db_t *db, isc_task_t *task) { + UNUSED(db); + UNUSED(task); +} + static dns_dbmethods_t sdb_methods = { attach, @@ -1227,7 +1233,8 @@ static dns_dbmethods_t sdb_methods = { issecure, nodecount, ispersistent, - overmem + overmem, + settask }; static isc_result_t diff --git a/lib/dns/zone.c b/lib/dns/zone.c index e04eac53d0..20b217db32 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.407 2004/03/02 02:37:11 marka Exp $ */ +/* $Id: zone.c,v 1.408 2004/03/04 06:56:39 marka Exp $ */ #include @@ -1046,6 +1046,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) { isc_result_totext(result)); goto cleanup; } + dns_db_settask(db, zone->task); if (! dns_db_ispersistent(db)) { if (zone->masterfile != NULL) { @@ -4049,6 +4050,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) { dns_result_totext(result)); goto cleanup; } + dns_db_settask(stub->db, zone->task); } dns_db_newversion(stub->db, &stub->version); @@ -5079,6 +5081,8 @@ dns_zone_settask(dns_zone_t *zone, isc_task_t *task) { if (zone->task != NULL) isc_task_detach(&zone->task); isc_task_attach(task, &zone->task); + if (zone->db != NULL) + dns_db_settask(zone->db, zone->task); UNLOCK_ZONE(zone); } @@ -5267,6 +5271,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { if (zone->db != NULL) dns_db_detach(&zone->db); dns_db_attach(db, &zone->db); + dns_db_settask(zone->db, zone->task); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); return (ISC_R_SUCCESS); diff --git a/lib/isc/task.c b/lib/isc/task.c index 4d8431915b..3027493604 100644 --- a/lib/isc/task.c +++ b/lib/isc/task.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: task.c,v 1.89 2003/10/25 00:09:13 jinmei Exp $ */ +/* $Id: task.c,v 1.90 2004/03/04 06:56:41 marka Exp $ */ /* * Principal Author: Bob Halley @@ -1132,7 +1132,7 @@ isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, } isc_thread_setconcurrency(workers); #else /* ISC_PLATFORM_USETHREADS */ - manager->refs = 0; + manager->refs = 1; taskmgr = manager; #endif /* ISC_PLATFORM_USETHREADS */