389-ds-base-1.3.4.6-1.fc23 freeipa-server-4.3 (jenkins build)
The deadlock occurs because two locks (replica and dbpage) are taken in the opposite order. One thread is processing the incoming starting replication session. The thread checks (while holding the replica lock) that the bind dn is part of the group of authorized replication managers. But because of period resync of that group it triggers a lookup of 'cn=replication managers,cn=sysaccounts,cn=etc,' that access some DB page in read (entryrdn index).
The other thread is processing a write operation that acquired the DB page (write), then a txn_be plugin triggers an internal op that needs a 'csn' (from replica csn generator). This generation of the CSN require the replica lock.
The deadlock is not systematic (because the resync of the replication managers group wait for a new replication session and has a minimum delay (60s))
Detailed analyze
The deadlock occurred between threads 27 and 34. Many others threads are victims of the deadlock
{{{ Thread 34 (ADD -> MEP update -> allocate csn) holds entryrdn page 23 wait for r->repl_lock
Thread 27 (incoming replication session) holds r->repl_lock wait for entryrdn page 23
8000619a WRITE 2 HELD userRoot/entryrdn.db page 23 (thread 34) 3fb READ 1 WAIT userRoot/entryrdn.db page 23 (thread 27) 46b READ 1 WAIT /var/lib/dirsrv/slapd-DOM-131-IDM-LAB-ENG-BRQ-REDHAT-COM/cldb/3e456119-d0f411e5-b0d3fd70-1222e87f_56bcdeb3000000040000.db page 35 471 READ 1 WAIT userRoot/objectclass.db page 5 402 READ 1 WAIT userRoot/objectclass.db page 5 48e READ 1 WAIT userRoot/objectclass.db page 5 48f READ 1 WAIT userRoot/objectclass.db page 5 3fd READ 1 WAIT userRoot/objectclass.db page 2 490 READ 1 WAIT userRoot/objectclass.db page 2 445 READ 1 WAIT userRoot/krbPrincipalName.db page 5
}}}
Thread 27 is refreshing (replica_updatedn_list_group_replace) the replica groupdn_list (authorized replication managers) from 'cn=replication managers,cn=sysaccounts,cn=etc,'
{{{ (gdb) thread [Current thread is 27 (Thread 0x7f66877f6700 (LWP 28964))] (gdb) where
Thread 34 is ADD that triggers an internal MOD (MEP plugin) that need to generate a csn.
{{{ Thread 34 (Thread 0x7f668affd700 (LWP 28957)):
In replica_updatedn_list_group_replace() we could separate the build of the new memberlist (without lock) and then do the replace with the lock
An other occurrence of this bug but this time when a ADD (updating the RUV) need to access the replica lock owned by the thread updating the authorized replication manager list
{{{ 3eb dd=149 locks held 0 write locks 0 pid/thread 24150/ 140228735989504 flags 0 priority 100 7f898bfef700 3eb READ 1 WAIT userRoot/entryrdn.db page 23
800064ac dd=6 locks held 41 write locks 32 pid/thread 24150/ 140228794738432 flags 0 priority 100 7f898f7f6700 800064ac WRITE 1 HELD /var/lib/dirsrv/slapd-/cldb/e1e9a005-ea1711e5-b358ed8b-eca27b34_56e70bd8000000040000.db page 15 800064ac READ 4 HELD userRoot/objectclass.db page 5 800064ac WRITE 2 HELD userRoot/objectclass.db page 5 800064ac WRITE 1 HELD userRoot/entryrdn.db page 23 800064ac WRITE 1 HELD userRoot/objectclass.db page 2 800064ac WRITE 1 HELD changelog/changenumber.db page 1 ...
Thread 31 (Thread 0x7f898f7f6700 (LWP 24174))::
Thread 24 (Thread 0x7f898bfef700 (LWP 24181)):
attachment 0001-Ticket-48597-Deadlock-when-rebuilding-the-group-of-a.patch
Hi Thierry, I have a question. It might be a stupid one, though... :)
This means at the line 1139, other threads could have a chance to set new r->groupdn_list and the line 1142-1144 could replace with this groupdn_list? It is guaranteed it does not occur or it is ok even if it occurs? If the answer is yes, I will ack. {{{ 1138 replica_unlock(r->repl_lock); 1139 replica_updatedn_list_group_replace(groupdn_list, updatedn_groupds_copy); 1140 replica_lock(r->repl_lock); 1141 1142 replica_updatedn_list_delete(r->groupdn_list, NULL); 1143 replica_updatedn_list_free(r->groupdn_list); 1144 r->groupdn_list = groupdn_list; 1145 slapi_valueset_free(updatedn_groupds_copy); }}}
Hi Noriko,
Good catch !!
The key element is r->updatedn_groups (nsDS5ReplicaBindDnGroup) that is updated while holding the lock. r->groupdn_list contains the list of members of those groups.
If during the refresh, 'nsDS5ReplicaBindDnGroup' is updated then there is a risk the updated groupdn_list is overwritten by the refresh. It should be a transient issue as the next refresh will evaluate the correct updatedn_groups. But if nsDS5ReplicaBindDnGroupCheckInterval is very long (or infinite), replication can break.
I think a possible fix is (after reacquiring replica lock), to check that updatedn_groupds_copy and r->updatedn_groups are identical.
attachment 0002-Ticket-48597-Deadlock-when-rebuilding-the-group-of-a.patch
Thank you, Thierry! Your take 2 patch looks nice!
Thanks Noriko for the review
git push origin '''master''' Counting objects: 7, done. Delta compression using up to 8 threads. Compressing objects: 100% (7/7), done. Writing objects: 100% (7/7), 2.30 KiB | 0 bytes/s, done. Total 7 (delta 5), reused 0 (delta 0) To ssh://git.fedorahosted.org/git/389/ds.git 6858dfd..5cfd3de master -> master
Metadata Update from @tbordaz: - Issue assigned to tbordaz - Issue set to the milestone: 1.3.5.0
389-ds-base is moving from Pagure to Github. This means that new issues and pull requests will be accepted only in 389-ds-base's github repository.
This issue has been cloned to Github and is available here: - https://github.com/389ds/389-ds-base/issues/1784
If you want to receive further updates on the issue, please navigate to the github issue and click on subscribe button.
subscribe
Thank you for understanding. We apologize for all inconvenience.
Metadata Update from @spichugi: - Issue close_status updated to: wontfix (was: Fixed)