From cd54ac9abe8d751373ecff64ee79d7b942a5be4d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Tue, 22 Sep 2020 16:24:06 +1000 Subject: [PATCH] Address lock-order-inversion WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) Cycle in lock order graph: M1 (0x000000000001) => M2 (0x000000000002) => M1 Mutex M2 acquired here while holding mutex M1 in thread T1: #0 pthread_rwlock_wrlock #1 isc_rwlock_lock lib/isc/rwlock.c:52:4 #2 zone_postload lib/dns/zone.c:5101:2 #3 receive_secure_db lib/dns/zone.c:16206:11 #4 dispatch lib/isc/task.c:1152:7 #5 run lib/isc/task.c:1344:2 Mutex M1 previously acquired by the same thread here: #0 pthread_mutex_lock #1 receive_secure_db lib/dns/zone.c:16204:2 #2 dispatch lib/isc/task.c:1152:7 #3 run lib/isc/task.c:1344:2 Mutex M1 acquired here while holding mutex M2 in thread T1: #0 pthread_mutex_lock #1 get_raw_serial lib/dns/zone.c:2518:2 #2 zone_gotwritehandle lib/dns/zone.c:2559:4 #3 dispatch lib/isc/task.c:1152:7 #4 run lib/isc/task.c:1344:2 Mutex M2 previously acquired by the same thread here: #0 pthread_rwlock_rdlock #1 isc_rwlock_lock lib/isc/rwlock.c:48:3 #2 zone_gotwritehandle lib/dns/zone.c:2552:2 #3 dispatch lib/isc/task.c:1152:7 #4 run lib/isc/task.c:1344:2 Thread T1 (running) created by main thread at: #0 pthread_create #1 isc_thread_create lib/isc/pthreads/thread.c:73:8 #2 isc_taskmgr_create lib/isc/task.c:1434:3 #3 create_managers bin/named/main.c:915:11 #4 setup bin/named/main.c:1223:11 #5 main bin/named/main.c:1523:2 SUMMARY: ThreadSanitizer: lock-order-inversion (potential deadlock) in pthread_rwlock_wrlock (cherry picked from commit 1090876693470eedf69211d0fe71ba2c88160f45) Conflict: NA Reference: https://gitlab.isc.org/isc-projects/bind9/-/commit/cd54ac9abe8d751373ecff64ee79d7b942a5be4d --- lib/dns/zone.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 096ff82f34..fd634af65f 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -2468,6 +2468,7 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { isc_result_t result = ISC_R_SUCCESS; dns_dbversion_t *version = NULL; dns_masterrawheader_t rawdata; + dns_db_t *db = NULL; REQUIRE(DNS_ZONE_VALID(zone)); INSIST(task == zone->task); @@ -2483,9 +2484,12 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { INSIST(zone != zone->raw); ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); if (zone->db != NULL) { + dns_db_attach(zone->db, &db); + } + ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + if (db != NULL) { const dns_master_style_t *output_style; - - dns_db_currentversion(zone->db, &version); + dns_db_currentversion(db, &version); dns_master_initrawheader(&rawdata); if (inline_secure(zone)) get_raw_serial(zone->raw, &rawdata); @@ -2495,15 +2499,18 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) { output_style = zone->masterstyle; else output_style = &dns_master_style_default; - result = dns_master_dumpinc3(zone->mctx, zone->db, version, + result = dns_master_dumpinc3(zone->mctx, db, version, output_style, zone->masterfile, zone->task, dump_done, zone, &zone->dctx, zone->masterformat, &rawdata); - dns_db_closeversion(zone->db, &version, false); - } else + dns_db_closeversion(db, &version, false); + } else { result = ISC_R_CANCELED; - ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read); + } + if (db != NULL) { + dns_db_detach(&db); + } UNLOCK_ZONE(zone); if (result != DNS_R_CONTINUE) goto fail; -- 2.23.0