diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Framework/TaskInventoryDictionary.cs | 164 |
1 files changed, 158 insertions, 6 deletions
diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 421bd5d..814758a 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs | |||
@@ -27,9 +27,13 @@ | |||
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Threading; | ||
31 | using System.Reflection; | ||
30 | using System.Xml; | 32 | using System.Xml; |
33 | using System.Diagnostics; | ||
31 | using System.Xml.Schema; | 34 | using System.Xml.Schema; |
32 | using System.Xml.Serialization; | 35 | using System.Xml.Serialization; |
36 | using log4net; | ||
33 | using OpenMetaverse; | 37 | using OpenMetaverse; |
34 | 38 | ||
35 | namespace OpenSim.Framework | 39 | namespace OpenSim.Framework |
@@ -45,6 +49,155 @@ namespace OpenSim.Framework | |||
45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 49 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 50 | ||
47 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); | 51 | private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); |
52 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
53 | |||
54 | private Thread LockedByThread; | ||
55 | private string WriterStack; | ||
56 | |||
57 | private Dictionary<Thread, string> ReadLockers = | ||
58 | new Dictionary<Thread, string>(); | ||
59 | |||
60 | /// <value> | ||
61 | /// An advanced lock for inventory data | ||
62 | /// </value> | ||
63 | private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
64 | |||
65 | /// <summary> | ||
66 | /// Are we readlocked by the calling thread? | ||
67 | /// </summary> | ||
68 | public bool IsReadLockedByMe() | ||
69 | { | ||
70 | if (m_itemLock.RecursiveReadCount > 0) | ||
71 | { | ||
72 | return true; | ||
73 | } | ||
74 | else | ||
75 | { | ||
76 | return false; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /// <summary> | ||
81 | /// Lock our inventory list for reading (many can read, one can write) | ||
82 | /// </summary> | ||
83 | public void LockItemsForRead(bool locked) | ||
84 | { | ||
85 | if (locked) | ||
86 | { | ||
87 | if (m_itemLock.IsWriteLockHeld && LockedByThread != null) | ||
88 | { | ||
89 | if (!LockedByThread.IsAlive) | ||
90 | { | ||
91 | //Locked by dead thread, reset. | ||
92 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | if (m_itemLock.RecursiveReadCount > 0) | ||
97 | { | ||
98 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
99 | try | ||
100 | { | ||
101 | StackTrace stackTrace = new StackTrace(); // get call stack | ||
102 | StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) | ||
103 | |||
104 | // write call stack method names | ||
105 | foreach (StackFrame stackFrame in stackFrames) | ||
106 | { | ||
107 | m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name | ||
108 | } | ||
109 | } | ||
110 | catch | ||
111 | {} | ||
112 | m_itemLock.ExitReadLock(); | ||
113 | } | ||
114 | if (m_itemLock.RecursiveWriteCount > 0) | ||
115 | { | ||
116 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
117 | m_itemLock.ExitWriteLock(); | ||
118 | } | ||
119 | |||
120 | while (!m_itemLock.TryEnterReadLock(60000)) | ||
121 | { | ||
122 | m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
123 | if (m_itemLock.IsWriteLockHeld) | ||
124 | { | ||
125 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
126 | System.Console.WriteLine("------------------------------------------"); | ||
127 | System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
128 | System.Console.WriteLine("------------------------------------------"); | ||
129 | System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
130 | System.Console.WriteLine("------------------------------------------"); | ||
131 | LockedByThread = null; | ||
132 | ReadLockers.Clear(); | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | else | ||
137 | { | ||
138 | if (m_itemLock.RecursiveReadCount>0) | ||
139 | { | ||
140 | m_itemLock.ExitReadLock(); | ||
141 | } | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /// <summary> | ||
146 | /// Lock our inventory list for writing (many can read, one can write) | ||
147 | /// </summary> | ||
148 | public void LockItemsForWrite(bool locked) | ||
149 | { | ||
150 | if (locked) | ||
151 | { | ||
152 | //Enter a write lock, wait indefinately for one to open. | ||
153 | if (m_itemLock.RecursiveReadCount > 0) | ||
154 | { | ||
155 | m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); | ||
156 | m_itemLock.ExitReadLock(); | ||
157 | } | ||
158 | if (m_itemLock.RecursiveWriteCount > 0) | ||
159 | { | ||
160 | m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
161 | m_itemLock.ExitWriteLock(); | ||
162 | } | ||
163 | while (!m_itemLock.TryEnterWriteLock(60000)) | ||
164 | { | ||
165 | if (m_itemLock.IsWriteLockHeld) | ||
166 | { | ||
167 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
168 | System.Console.WriteLine("------------------------------------------"); | ||
169 | System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
170 | System.Console.WriteLine("------------------------------------------"); | ||
171 | System.Console.WriteLine("Locker's call stack:\n" + WriterStack); | ||
172 | System.Console.WriteLine("------------------------------------------"); | ||
173 | } | ||
174 | else | ||
175 | { | ||
176 | m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by a reader. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); | ||
177 | System.Console.WriteLine("------------------------------------------"); | ||
178 | System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); | ||
179 | System.Console.WriteLine("------------------------------------------"); | ||
180 | foreach (KeyValuePair<Thread, string> kvp in ReadLockers) | ||
181 | { | ||
182 | System.Console.WriteLine("Locker name {0} call stack:\n" + kvp.Value, kvp.Key.Name); | ||
183 | System.Console.WriteLine("------------------------------------------"); | ||
184 | } | ||
185 | } | ||
186 | m_itemLock = new System.Threading.ReaderWriterLockSlim(); | ||
187 | ReadLockers.Clear(); | ||
188 | } | ||
189 | |||
190 | LockedByThread = Thread.CurrentThread; | ||
191 | WriterStack = Environment.StackTrace; | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | if (m_itemLock.RecursiveWriteCount > 0) | ||
196 | { | ||
197 | m_itemLock.ExitWriteLock(); | ||
198 | } | ||
199 | } | ||
200 | } | ||
48 | 201 | ||
49 | #region ICloneable Members | 202 | #region ICloneable Members |
50 | 203 | ||
@@ -52,14 +205,13 @@ namespace OpenSim.Framework | |||
52 | { | 205 | { |
53 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); | 206 | TaskInventoryDictionary clone = new TaskInventoryDictionary(); |
54 | 207 | ||
55 | lock (this) | 208 | m_itemLock.EnterReadLock(); |
209 | foreach (UUID uuid in Keys) | ||
56 | { | 210 | { |
57 | foreach (UUID uuid in Keys) | 211 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); |
58 | { | ||
59 | clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); | ||
60 | } | ||
61 | } | 212 | } |
62 | 213 | m_itemLock.ExitReadLock(); | |
214 | |||
63 | return clone; | 215 | return clone; |
64 | } | 216 | } |
65 | 217 | ||