Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
BIND
Commits
502dac3e
Commit
502dac3e
authored
Nov 22, 1999
by
Bob Halley
Browse files
revise shutdown process
parent
66dfced5
Changes
1
Hide whitespace changes
Inline
Side-by-side
lib/dns/resolver.c
View file @
502dac3e
...
...
@@ -198,6 +198,7 @@ struct dns_resolver {
/* Locked by lock. */
unsigned
int
references
;
isc_boolean_t
exiting
;
isc_eventlist_t
whenshutdown
;
isc_socket_t
*
udpsocket4
;
isc_socket_t
*
udpsocket6
;
dns_dispatch_t
*
dispatch4
;
...
...
@@ -1135,7 +1136,8 @@ fctx_destroy(fetchctx_t *fctx) {
*/
REQUIRE
(
VALID_FCTX
(
fctx
));
REQUIRE
(
fctx
->
state
==
fetchstate_done
);
REQUIRE
(
fctx
->
state
==
fetchstate_done
||
fctx
->
state
==
fetchstate_init
);
REQUIRE
(
ISC_LIST_EMPTY
(
fctx
->
events
));
REQUIRE
(
ISC_LIST_EMPTY
(
fctx
->
queries
));
REQUIRE
(
ISC_LIST_EMPTY
(
fctx
->
finds
));
...
...
@@ -1195,7 +1197,39 @@ fctx_timeout(isc_task_t *task, isc_event_t *event) {
}
static
void
fctx_shutdown
(
isc_task_t
*
task
,
isc_event_t
*
event
)
{
fctx_shutdown
(
fetchctx_t
*
fctx
)
{
isc_event_t
*
cevent
;
/*
* Start the shutdown process for fctx, if it isn't already underway.
*/
FCTXTRACE
(
"shutdown"
);
/*
* The caller must be holding the appropriate bucket lock.
*/
if
(
fctx
->
want_shutdown
)
return
;
fctx
->
want_shutdown
=
ISC_TRUE
;
/*
* Unless we're still initializing (in which case the
* control event is still outstanding), we need to post
* the control event to tell the fetch we want it to
* exit.
*/
if
(
fctx
->
state
!=
fetchstate_init
)
{
cevent
=
&
fctx
->
control_event
;
isc_task_send
(
fctx
->
res
->
buckets
[
fctx
->
bucketnum
].
task
,
&
cevent
);
}
}
static
void
fctx_doshutdown
(
isc_task_t
*
task
,
isc_event_t
*
event
)
{
fetchctx_t
*
fctx
=
event
->
arg
;
isc_boolean_t
bucket_empty
=
ISC_FALSE
;
dns_resolver_t
*
res
;
...
...
@@ -1207,7 +1241,7 @@ fctx_shutdown(isc_task_t *task, isc_event_t *event) {
bucketnum
=
fctx
->
bucketnum
;
(
void
)
task
;
/* Keep compiler quiet. */
FCTXTRACE
(
"shutdown"
);
FCTXTRACE
(
"
do
shutdown"
);
fctx
->
attributes
|=
FCTX_ATTR_SHUTTINGDOWN
;
...
...
@@ -1270,8 +1304,8 @@ fctx_start(isc_task_t *task, isc_event_t *event) {
* the fctx.
*/
ISC_EVENT_INIT
(
event
,
sizeof
*
event
,
0
,
NULL
,
DNS_EVENT_FETCHCONTROL
,
fctx_shutdown
,
fctx
,
(
void
*
)
fctx_shutdown
,
NULL
,
NULL
);
DNS_EVENT_FETCHCONTROL
,
fctx_
do
shutdown
,
fctx
,
(
void
*
)
fctx_
do
shutdown
,
NULL
,
NULL
);
}
UNLOCK
(
&
res
->
buckets
[
bucketnum
].
lock
);
...
...
@@ -2920,9 +2954,27 @@ destroy(dns_resolver_t *res) {
}
static
void
empty_bucket
(
dns_resolver_t
*
res
)
{
isc_boolean_t
need_destroy
=
ISC_FALSE
;
send_shutdown_events
(
dns_resolver_t
*
res
)
{
isc_event_t
*
event
,
*
next_event
;
isc_task_t
*
etask
;
/*
* Caller must be holding the resolver lock.
*/
for
(
event
=
ISC_LIST_HEAD
(
res
->
whenshutdown
);
event
!=
NULL
;
event
=
next_event
)
{
next_event
=
ISC_LIST_NEXT
(
event
,
link
);
ISC_LIST_UNLINK
(
res
->
whenshutdown
,
event
,
link
);
etask
=
event
->
sender
;
event
->
sender
=
res
;
isc_task_sendanddetach
(
&
etask
,
&
event
);
}
}
static
void
empty_bucket
(
dns_resolver_t
*
res
)
{
RTRACE
(
"empty_bucket"
);
LOCK
(
&
res
->
lock
);
...
...
@@ -2930,12 +2982,9 @@ empty_bucket(dns_resolver_t *res) {
INSIST
(
res
->
activebuckets
>
0
);
res
->
activebuckets
--
;
if
(
res
->
activebuckets
==
0
)
need_destroy
=
ISC_TRUE
;
send_shutdown_events
(
res
)
;
UNLOCK
(
&
res
->
lock
);
if
(
need_destroy
)
destroy
(
res
);
}
isc_result_t
...
...
@@ -3048,6 +3097,7 @@ dns_resolver_create(dns_view_t *view,
res
->
references
=
1
;
res
->
exiting
=
ISC_FALSE
;
ISC_LIST_INIT
(
res
->
whenshutdown
);
result
=
isc_mutex_init
(
&
res
->
lock
);
if
(
result
!=
ISC_R_SUCCESS
)
...
...
@@ -3108,27 +3158,57 @@ dns_resolver_attach(dns_resolver_t *source, dns_resolver_t **targetp) {
}
void
dns_resolver_detach
(
dns_resolver_t
**
resp
)
{
dns_resolver_t
*
res
;
isc_boolean_t
need_destroy
=
ISC_FALSE
;
dns_resolver_whenshutdown
(
dns_resolver_t
*
res
,
isc_task_t
*
task
,
isc_event_t
**
eventp
)
{
isc_task_t
*
clone
;
isc_event_t
*
event
;
REQUIRE
(
VALID_RESOLVER
(
res
));
REQUIRE
(
eventp
!=
NULL
);
event
=
*
eventp
;
*
eventp
=
NULL
;
LOCK
(
&
res
->
lock
);
if
(
res
->
exiting
&&
res
->
activebuckets
==
0
)
{
/*
* We're already shutdown. Send the event.
*/
event
->
sender
=
res
;
isc_task_send
(
task
,
&
event
);
}
else
{
clone
=
NULL
;
isc_task_attach
(
task
,
&
clone
);
event
->
sender
=
clone
;
ISC_LIST_APPEND
(
res
->
whenshutdown
,
event
,
link
);
}
UNLOCK
(
&
res
->
lock
);
}
void
dns_resolver_shutdown
(
dns_resolver_t
*
res
)
{
unsigned
int
i
;
fetchctx_t
*
fctx
;
REQUIRE
(
resp
!=
NULL
);
res
=
*
resp
;
REQUIRE
(
VALID_RESOLVER
(
res
));
RTRACE
(
"detach"
);
RTRACE
(
"shutdown"
);
LOCK
(
&
res
->
lock
);
INSIST
(
res
->
references
>
0
);
res
->
references
--
;
if
(
res
->
references
==
0
)
{
if
(
!
res
->
exiting
)
{
RTRACE
(
"exiting"
);
res
->
exiting
=
ISC_TRUE
;
for
(
i
=
0
;
i
<
res
->
nbuckets
;
i
++
)
{
/*
* XXXRTH Post shutdown events?
*/
LOCK
(
&
res
->
buckets
[
i
].
lock
);
for
(
fctx
=
ISC_LIST_HEAD
(
res
->
buckets
[
i
].
fctxs
);
fctx
!=
NULL
;
fctx
=
ISC_LIST_NEXT
(
fctx
,
link
))
fctx_shutdown
(
fctx
);
if
(
res
->
udpsocket4
!=
NULL
)
isc_socket_cancel
(
res
->
udpsocket4
,
res
->
buckets
[
i
].
task
,
...
...
@@ -3145,8 +3225,40 @@ dns_resolver_detach(dns_resolver_t **resp) {
UNLOCK
(
&
res
->
buckets
[
i
].
lock
);
}
if
(
res
->
activebuckets
==
0
)
need_destroy
=
ISC_TRUE
;
send_shutdown_events
(
res
)
;
}
UNLOCK
(
&
res
->
lock
);
}
/*
* XXXRTH Do we need attach/detach semantics for the resolver and the
* adb? They can't be used separately, and the references to
* them in the view MUST exist until they're both shutdown.
* Using create/destroy is probably better. Allow attach/detach
* to be done at the view level.
*/
void
dns_resolver_detach
(
dns_resolver_t
**
resp
)
{
dns_resolver_t
*
res
;
isc_boolean_t
need_destroy
=
ISC_FALSE
;
REQUIRE
(
resp
!=
NULL
);
res
=
*
resp
;
REQUIRE
(
VALID_RESOLVER
(
res
));
RTRACE
(
"detach"
);
LOCK
(
&
res
->
lock
);
INSIST
(
res
->
references
>
0
);
res
->
references
--
;
if
(
res
->
references
==
0
)
{
INSIST
(
res
->
exiting
&&
res
->
activebuckets
==
0
);
need_destroy
=
ISC_TRUE
;
}
UNLOCK
(
&
res
->
lock
);
if
(
need_destroy
)
...
...
@@ -3331,8 +3443,9 @@ void
dns_resolver_destroyfetch
(
dns_resolver_t
*
res
,
dns_fetch_t
**
fetchp
)
{
dns_fetch_t
*
fetch
;
dns_fetchevent_t
*
event
,
*
next_event
;
isc_event_t
*
cevent
;
fetchctx_t
*
fctx
;
unsigned
int
bucketnum
;
isc_boolean_t
bucket_empty
=
ISC_FALSE
;
REQUIRE
(
fetchp
!=
NULL
);
fetch
=
*
fetchp
;
...
...
@@ -3341,11 +3454,12 @@ dns_resolver_destroyfetch(dns_resolver_t *res, dns_fetch_t **fetchp) {
FTRACE
(
"destroyfetch"
);
LOCK
(
&
res
->
buckets
[
fctx
->
bucketnum
].
lock
);
bucketnum
=
fctx
->
bucketnum
;
LOCK
(
&
res
->
buckets
[
bucketnum
].
lock
);
/*
* Sanity check
. T
he caller should have
either
gotten its
*
fetchevent before
trying to destroy the fetch.
* Sanity check
: t
he caller should have gotten its
event before
* trying to destroy the fetch.
*/
event
=
NULL
;
if
(
fctx
->
state
!=
fetchstate_done
)
{
...
...
@@ -3362,25 +3476,26 @@ dns_resolver_destroyfetch(dns_resolver_t *res, dns_fetch_t **fetchp) {
if
(
fctx
->
references
==
0
)
{
/*
* No one cares about the result of this fetch anymore.
* Shut it down.
*/
fctx
->
want_shutdown
=
ISC_TRUE
;
/*
* Unless we're still initializing (in which case the
* control event is still outstanding), we need to post
* the control event to tell the fetch we want it to
* exit.
*/
if
(
fctx
->
state
!=
fetchstate_init
)
{
cevent
=
&
fctx
->
control_event
;
isc_task_send
(
res
->
buckets
[
fctx
->
bucketnum
].
task
,
&
cevent
);
if
(
fctx
->
pending
==
0
&&
SHUTTINGDOWN
(
fctx
))
{
/*
* This fctx is already shutdown; we were just
* waiting for the last reference to go away.
*/
bucket_empty
=
fctx_destroy
(
fctx
);
}
else
{
/*
* Initiate shutdown.
*/
fctx_shutdown
(
fctx
);
}
}
UNLOCK
(
&
res
->
buckets
[
fctx
->
bucketnum
].
lock
);
UNLOCK
(
&
res
->
buckets
[
bucketnum
].
lock
);
isc_mem_put
(
res
->
mctx
,
fetch
,
sizeof
*
fetch
);
*
fetchp
=
NULL
;
if
(
bucket_empty
)
empty_bucket
(
res
);
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment