[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
[no subject]
#
# slapd ldbm cache problem. ITS#39
#
# This script will cause slapd to hang in a loop
# after deleting the one entry.
#
# To cause the hanging loop you have to decrease the cache
# size to 5 in slapd/back-ldbm/back-ldbm.h
# sinze th loop is caused only when the system tries to free up
# the corrupted cache entry that was caused by the delete.
#
# The problem is that the cache is sorted by using the dn's
# however some dn's are normalized and others are not.
# Using the data below the cache is not built in
# normalized dn order, it's built based on the dn's
# used by the calling routine. ldapsearch populates the
# cache with non-normalized dn's, but delete search based on the
# cache being sorted based on a normalized dn. So if the
# cache is out of order based on the noramlized dn the delete
# fails to remove the item from the cache. (id2entry.c)
# This corrupts the cache so that latter when the cache has reached
# max size and the corrupted entry is tring to be cleared.
# an infinite loop is encountered (back-ldbm/cache.c)
# /*
# * found at least one to delete - try to get back under
# * the max cache size.
# */
# while ( cache->c_lrutail != NULL && cache->c_lrutail->e_refcnt
# == 0 && cache->c_cursize > cache->c_maxsize ) {
#
# e = cache->c_lrutail;
#
# /* XXX check for writer lock - should also check no readers pending */
##ifdef LDAP_DEBUG
# assert(!pthread_rdwr_rwchk_np(&e->e_rdwr));
##endif
# /* delete from cache and lru q */
#
# // This code fails, on the corrupted entry. RWR
# rc = cache_delete_entry_internal( cache, e );
#
# // Since the above fails the conditions for this loop
# // this will be done until crash
# entry_free( e );
#
# }
#
# Fixes
# The easiest way for me was to add:
# dn_normalize( e->e_dn );
# at the start of cache_add_entry_lock() (back-ldbm/cache.c)
#
# The problem with this is that all dn entries in the database
# will be stored in normalized form. ( not really a problem at least for
# me). But ldif2ldbm should also reflect this since any existing
# dn's need to be changed.
#
#
# Anyways, if you run the script below it will cause the error.
# The last search is commented out since it will loop slapd,
# but if you search the err file you will see the could not delete from
# cache entry.
#
cat > testdata <<!
dn: c=US
objectclass: country
c: US
dn: o=Cache Test1,c=Us
objectclass: organization
o: Cache Test1
dn: o=Cache Test2,c=Us
objectclass: organization
o: Cache Test2
dn: o=Cache Test3, c=Us
objectclass: organization
o: Cache Test3
dn: cn=CacheTest,o=Cache Test1,c=US
cn: CacheTest
sn: CacheTest
o: Cache Test1
dn: cn=CacheTest,o=Cache Test2,c=US
cn: CacheTest
sn: CacheTest
o: Cache Test2
dn: cn=CacheTest, o=Cache Test3, c=US
cn: CacheTest
sn: CacheTest
o: Cache Test3
dn: cn=CacheTesta, o=Cache Test3, c=US
cn: CacheTest
sn: CacheTest
o: Cache Test3
!
ldif2ldbm -i testdata -f slapd.conf
./slapd -d129 -f slapd.conf 2>err &
ldapsearch "cn=Ca*"
# This delete will cause slapd to generate a could not delete from cache
# error.
ldapdelete -D cn=xyzzy -w password "cn=CacheTest, o=Cache Test3, c=US"
# Warning on my system this search will cause slapd to hang
# in a loop generating a large err file.
# I had to kill it with a kill -9
# ldapsearch "cn=Ca*"