This is an automated email from the ASF dual-hosted git repository. nightowl888 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/lucenenet.git
commit 7f6c78570d4b7e5e4bbb8708acfe3a397822baca Author: sourcerist <[email protected]> AuthorDate: Fri Feb 8 14:44:47 2019 -0800 fix locking/disposal bug --- src/Lucene.Net/Store/NativeFSLockFactory.cs | 72 ++++++++++++++++------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/src/Lucene.Net/Store/NativeFSLockFactory.cs b/src/Lucene.Net/Store/NativeFSLockFactory.cs index b5b65fc..6b253b8 100644 --- a/src/Lucene.Net/Store/NativeFSLockFactory.cs +++ b/src/Lucene.Net/Store/NativeFSLockFactory.cs @@ -88,16 +88,17 @@ namespace Lucene.Net.Store SetLockDir(lockDir); } - // LUCENENET: NativeFSLocks in Java are infact singletons; this is how we mimick that to track instances and make sure - // IW.Unlock and IW.IsLocked works correctly - internal static readonly Dictionary<string, Lock> _locks = new Dictionary<string, Lock>(); - - /// <summary> - /// Given a lock name, return the full prefixed path of the actual lock file. - /// </summary> - /// <param name="lockName"></param> - /// <returns></returns> - private string GetCanonicalPathOfLockFile(string lockName) + // LUCENENET: NativeFSLocks in Java are infact singletons; this is how we mimick that to track instances and make sure + // IW.Unlock and IW.IsLocked works correctly + private static readonly Dictionary<string, Lock> _locks = new Dictionary<string, Lock>(); + private static readonly object _locks_lockObj = new object(); + + /// <summary> + /// Given a lock name, return the full prefixed path of the actual lock file. + /// </summary> + /// <param name="lockName"></param> + /// <returns></returns> + private string GetCanonicalPathOfLockFile(string lockName) { if (m_lockPrefix != null) { @@ -110,9 +111,11 @@ namespace Lucene.Net.Store { var path = GetCanonicalPathOfLockFile(lockName); Lock l; - lock (_locks) - if (!_locks.TryGetValue(path, out l)) - _locks.Add(path, l = NewLock(path)); + lock (_locks_lockObj) + { + if (!_locks.TryGetValue(path, out l)) + _locks.Add(path, l = NewLock(path)); + } return l; } @@ -130,14 +133,16 @@ namespace Lucene.Net.Store { var path = GetCanonicalPathOfLockFile(lockName); Lock l; - // this is the reason why we can't use ConcurrentDictionary: we need the removal and disposal of the lock to be atomic - // otherwise it may clash with MakeLock making a lock and ClearLock disposing of it in another thread. - lock (_locks) - if (_locks.TryGetValue(path, out l)) - { - _locks.Remove(path); - l.Dispose(); - } + // this is the reason why we can't use ConcurrentDictionary: we need the removal and disposal of the lock to be atomic + // otherwise it may clash with MakeLock making a lock and ClearLock disposing of it in another thread. + lock (_locks_lockObj) + { + if (_locks.TryGetValue(path, out l)) + { + _locks.Remove(path); + l.Dispose(); + } + } } } @@ -164,6 +169,7 @@ namespace Lucene.Net.Store private FileStream channel; private readonly string path; private readonly DirectoryInfo lockDir; + private readonly object lockObject = new object(); // avoid lock(this) public NativeFSLock(NativeFSLockFactory outerInstance, DirectoryInfo lockDir, string path) { @@ -174,7 +180,7 @@ namespace Lucene.Net.Store public override bool Obtain() { - lock (this) + lock (lockObject) { FailureReason = null; @@ -242,15 +248,15 @@ namespace Lucene.Net.Store { if (disposing) { - lock (this) + lock (lockObject) { // whether or not we have created a file, we need to remove // the lock instance from the dictionary that tracks them. try { - lock (NativeFSLockFactory._locks) - NativeFSLockFactory._locks.Remove(path); - } + outerInstance?.ClearLock(path); + + } finally { if (channel != null) @@ -285,7 +291,7 @@ namespace Lucene.Net.Store public override bool IsLocked() { - lock (this) + lock (lockObject) { // The test for is isLocked is not directly possible with native file locks: @@ -336,8 +342,9 @@ namespace Lucene.Net.Store private FileStream channel; private readonly string path; private readonly DirectoryInfo lockDir; + private readonly object lockObject = new object(); // avoid lock(this) - public SharingAwareNativeFSLock(NativeFSLockFactory outerInstance, DirectoryInfo lockDir, string path) + public SharingAwareNativeFSLock(NativeFSLockFactory outerInstance, DirectoryInfo lockDir, string path) { this.outerInstance = outerInstance; this.lockDir = lockDir; @@ -376,7 +383,7 @@ namespace Lucene.Net.Store public override bool Obtain() { - lock (this) + lock (lockObject) { FailureReason = null; @@ -461,14 +468,13 @@ namespace Lucene.Net.Store { if (disposing) { - lock (this) + lock (lockObject) { // whether or not we have created a file, we need to remove // the lock instance from the dictionary that tracks them. try { - lock (NativeFSLockFactory._locks) - NativeFSLockFactory._locks.Remove(path); + outerInstance?.ClearLock(path); } finally { @@ -500,7 +506,7 @@ namespace Lucene.Net.Store public override bool IsLocked() { - lock (this) + lock (lockObject) { // First a shortcut, if a lock reference in this instance is available if (channel != null)
