isc_refcount_t sends; /*%< Send in progress */
isc_refcount_t recvs; /*%< Receive in progress */
- bool shuttingdown;
+ atomic_bool shuttingdown;
isc_result_t shutdown_result;
result = xfrin_start(xfr);
if (result != ISC_R_SUCCESS) {
- xfr->shuttingdown = true;
+ atomic_store(&xfr->shuttingdown, true);
xfr->shutdown_result = result;
dns_xfrin_detach(xfrp);
}
return (result);
}
+static void
+xfrin_cancelio(dns_xfrin_ctx_t *xfr);
+
void
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
REQUIRE(VALID_XFRIN(xfr));
- if (!xfr->shuttingdown) {
- xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
- }
+
+ xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
}
void
static void
xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
- if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) {
- xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
- isc_result_totext(result));
- if (xfr->is_ixfr) {
- /* Pass special result code to force AXFR retry */
- result = DNS_R_BADIXFR;
+ /* Make sure only the first xfrin_fail() trumps */
+ if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false },
+ true)) {
+ if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS)
+ {
+ xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
+ isc_result_totext(result));
+ if (xfr->is_ixfr) {
+ /* Pass special result code to force AXFR retry
+ */
+ result = DNS_R_BADIXFR;
+ }
}
+ xfrin_cancelio(xfr);
+ /*
+ * Close the journal.
+ */
+ if (xfr->ixfr.journal != NULL) {
+ dns_journal_destroy(&xfr->ixfr.journal);
+ }
+ if (xfr->done != NULL) {
+ (xfr->done)(xfr->zone, result);
+ xfr->done = NULL;
+ }
+ xfr->shutdown_result = result;
}
- xfrin_cancelio(xfr);
- /*
- * Close the journal.
- */
- if (xfr->ixfr.journal != NULL) {
- dns_journal_destroy(&xfr->ixfr.journal);
- }
- if (xfr->done != NULL) {
- (xfr->done)(xfr->zone, result);
- xfr->done = NULL;
- }
- xfr->shuttingdown = true;
- xfr->shutdown_result = result;
}
static void
isc_tlsctx_free(&xfr->tlsctx);
}
- if (xfr->shuttingdown) {
+ if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
CHECK(xfrin_send_request(xfr));
failure:
- if (result != ISC_R_SUCCESS && result != ISC_R_SHUTTINGDOWN) {
+ if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed to connect");
}
REQUIRE(VALID_XFRIN(xfr));
isc_refcount_decrement0(&xfr->sends);
- if (xfr->shuttingdown) {
+ if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
isc_nm_read(recv_xfr->handle, xfrin_recv_done, recv_xfr);
failure:
- if (result != ISC_R_SUCCESS && result != ISC_R_SHUTTINGDOWN) {
+ if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed sending request data");
}
isc_refcount_decrement0(&xfr->recvs);
- if (xfr->shuttingdown) {
+ if (atomic_load(&xfr->shuttingdown)) {
result = ISC_R_SHUTTINGDOWN;
}
xfr->done = NULL;
}
- xfr->shuttingdown = true;
+ atomic_store(&xfr->shuttingdown, true);
xfr->shutdown_result = ISC_R_SUCCESS;
break;
default:
}
failure:
- if (result != ISC_R_SUCCESS && result != ISC_R_SHUTTINGDOWN) {
+ if (result != ISC_R_SUCCESS) {
xfrin_fail(xfr, result, "failed while receiving responses");
}
REQUIRE(VALID_XFRIN(xfr));
/* Safe-guards */
- REQUIRE(xfr->shuttingdown);
+ REQUIRE(atomic_load(&xfr->shuttingdown));
isc_refcount_destroy(&xfr->references);
isc_refcount_destroy(&xfr->connects);
isc_refcount_destroy(&xfr->recvs);