APR mutexes don't support recursive locking on all platforms. As a result, trying to take out the same lock twice in the same thread will ca…
APR mutexes don't support recursive locking on all platforms.As a result, trying to take out the same lock twice in thesame thread will cause a lock up under e.g. Linux. This patchadds an option to svn_mutex__t that detects recursive lockingattempts in most cases and returns a proper error.The idea is simply to store the thread ID of the lock OWNERalong the actual mutex object. If that matches the currentthread's ID, there is a violation. As the current threadcannot race with itself and because any other thread uses adifferent thread ID, setting and comparing this aux. info canbe done safely.Also, we may allow for false negatives here since we only tryto detect code sequences that are already illegal in the firstplace. We also don't make that check mandatory as access tothread IDs and their comparison may be somewhat expensive onsome systems - which would impair the futex-like behavior thatwe assume in some places like the caches.A more detailed description has been added to the source code.A FSFS-based test is added as that has been the origin of thefeature request.Current users will be updated as follows. FS level locks andlibrary / module initialization will enable recursion detection.Potentially runtime critical, internal use disables it.* subversion/include/svn_error_codes.h (SVN_ERR_RECURSIVE_LOCK): Define a new error code for invalid locking schemes.* subversion/include/private/svn_mutex.h (svn_mutex__t): Our mutex is now a struct as we add aux. data to it. (svn_mutex__init): Add the CHECKED option.* subversion/libsvn_subr/mutex.c (svn_mutex__t): Define the mutex structure and and document the aux. data extensively. (svn_mutex__init): Update constructor. (svn_mutex__lock): Optionally, check for recursive locking attempts and update the associtated aux. data. (svn_mutex__unlock): Optionally, update the aux. data for recursive lock detection.* subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c (never_reached, lock_again): Callback functions required by the new test. (recursive_locking): New test expecting an SVN_ERR_RECURSIVE_LOCK. (test_funcs): Register the new test.* subversion/libsvn_fs_base/bdb/env.c (bdb_init_cb): Initialization code should detect recursions.* subversion/libsvn_fs/fs-loader.c (synchronized_initialize): Same.* subversion/libsvn_subr/dso.c (svn_dso_initialize2): Same.* subversion/libsvn_fs_fs/fs.c (fs_serialized_init): FS-level locks shall detect recursion do aid API users.* subversion/libsvn_fs_x/fs.c (x_serialized_init): Same.* subversion/libsvn_ra_svn/cyrus_auth.c (sasl_mutex_alloc_cb_internal, svn_ra_svn__sasl_common_init): Internal, potentially tightly used mutexes shall not suffer the overhead.* subversion/libsvn_subr/cache-inprocess.c (svn_cache__create_inprocess): Same.* subversion/libsvn_subr/cache-membuffer.c (svn_cache__membuffer_cache_create, svn_cache__create_membuffer_cache): Same.* subversion/libsvn_subr/file.c (init_handle_pool): Same.* subversion/libsvn_subr/named_atomic.c (init_thread_mutex): Same.* subversion/libsvn_subr/object_pool.c (svn_object_pool__create): Same.* subversion/libsvn_subr/root_pools.c (svn_root_pools__create): Same.* subversion/libsvn_subr/utf.c (svn_utf_initialize2): Same.* subversion/svnserve/logger.c (logger__create_for_stderr, logger__create): Same.* subversion/tests/svn_test_main.c (svn_test_main): For best test coverage, we enable recursion detection in our test suite main app.