You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2019/07/09 21:29:33 UTC
[lucenenet] 17/29: fix locking/disposal bug
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 <sp...@gmail.com>
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)