aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
authorCasperW2009-11-27 18:29:03 +0100
committerCasperW2009-11-30 21:17:15 +0100
commit9888f95068373f1bfdb289e85560a7d873d22696 (patch)
tree406867a636ba643eb91d7af860a8b01b73e11a51 /OpenSim/Region/ScriptEngine
parentMerge branch 'master' into careminster (diff)
downloadopensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.zip
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.gz
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.bz2
opensim-SC_OLD-9888f95068373f1bfdb289e85560a7d873d22696.tar.xz
Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim.
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs11
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs415
2 files changed, 254 insertions, 172 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ec771e3..267928b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2950,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2950 return m_host.OwnerID.ToString(); 2950 return m_host.OwnerID.ToString();
2951 } 2951 }
2952 2952
2953 [DebuggerNonUserCode]
2953 public void llInstantMessage(string user, string message) 2954 public void llInstantMessage(string user, string message)
2954 { 2955 {
2956 UUID result;
2957 if (!UUID.TryParse(user, out result))
2958 {
2959 throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user));
2960 return;
2961 }
2962
2963
2955 m_host.AddScriptLPS(1); 2964 m_host.AddScriptLPS(1);
2956 2965
2957 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 2966 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
@@ -2966,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2966 UUID friendTransactionID = UUID.Random(); 2975 UUID friendTransactionID = UUID.Random();
2967 2976
2968 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); 2977 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
2969 2978
2970 GridInstantMessage msg = new GridInstantMessage(); 2979 GridInstantMessage msg = new GridInstantMessage();
2971 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 2980 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid;
2972 msg.toAgentID = new Guid(user); // toAgentID.Guid; 2981 msg.toAgentID = new Guid(user); // toAgentID.Guid;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index d997ea3..49c69ab 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -101,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
101 private Dictionary<UUID, IScriptInstance> m_Scripts = 101 private Dictionary<UUID, IScriptInstance> m_Scripts =
102 new Dictionary<UUID, IScriptInstance>(); 102 new Dictionary<UUID, IScriptInstance>();
103 103
104 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
105
104 // Maps the asset ID to the assembly 106 // Maps the asset ID to the assembly
105 107
106 private Dictionary<UUID, string> m_Assemblies = 108 private Dictionary<UUID, string> m_Assemblies =
@@ -122,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
122 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); 124 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
123 IWorkItemResult m_CurrentCompile = null; 125 IWorkItemResult m_CurrentCompile = null;
124 126
127 private void lockScriptsForRead(bool locked)
128 {
129 if (locked)
130 {
131 if (m_scriptsLock.RecursiveReadCount > 0)
132 {
133 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
134 m_scriptsLock.ExitReadLock();
135 }
136 if (m_scriptsLock.RecursiveWriteCount > 0)
137 {
138 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
139 m_scriptsLock.ExitWriteLock();
140 }
141
142 while (!m_scriptsLock.TryEnterReadLock(60000))
143 {
144 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
145 if (m_scriptsLock.IsWriteLockHeld)
146 {
147 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
148 }
149 }
150 }
151 else
152 {
153 m_scriptsLock.ExitReadLock();
154 }
155 }
156 private void lockScriptsForWrite(bool locked)
157 {
158 if (locked)
159 {
160 if (m_scriptsLock.RecursiveReadCount > 0)
161 {
162 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
163 m_scriptsLock.ExitReadLock();
164 }
165 if (m_scriptsLock.RecursiveWriteCount > 0)
166 {
167 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
168 m_scriptsLock.ExitWriteLock();
169 }
170
171 while (!m_scriptsLock.TryEnterWriteLock(60000))
172 {
173 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
174 if (m_scriptsLock.IsWriteLockHeld)
175 {
176 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
177 }
178 }
179 }
180 else
181 {
182 m_scriptsLock.ExitWriteLock();
183 }
184 }
185
125 public string ScriptEngineName 186 public string ScriptEngineName
126 { 187 {
127 get { return "XEngine"; } 188 get { return "XEngine"; }
@@ -261,43 +322,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
261 322
262 public void RemoveRegion(Scene scene) 323 public void RemoveRegion(Scene scene)
263 { 324 {
264 lock (m_Scripts) 325 lockScriptsForRead(true);
326 foreach (IScriptInstance instance in m_Scripts.Values)
265 { 327 {
266 foreach (IScriptInstance instance in m_Scripts.Values) 328 // Force a final state save
329 //
330 if (m_Assemblies.ContainsKey(instance.AssetID))
267 { 331 {
268 // Force a final state save 332 string assembly = m_Assemblies[instance.AssetID];
269 // 333 instance.SaveState(assembly);
270 if (m_Assemblies.ContainsKey(instance.AssetID)) 334 }
271 {
272 string assembly = m_Assemblies[instance.AssetID];
273 instance.SaveState(assembly);
274 }
275 335
276 // Clear the event queue and abort the instance thread 336 // Clear the event queue and abort the instance thread
277 // 337 //
278 instance.ClearQueue(); 338 instance.ClearQueue();
279 instance.Stop(0); 339 instance.Stop(0);
280 340
281 // Release events, timer, etc 341 // Release events, timer, etc
282 // 342 //
283 instance.DestroyScriptInstance(); 343 instance.DestroyScriptInstance();
284 344
285 // Unload scripts and app domains 345 // Unload scripts and app domains
286 // Must be done explicitly because they have infinite 346 // Must be done explicitly because they have infinite
287 // lifetime 347 // lifetime
288 // 348 //
289 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 349 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
290 if (m_DomainScripts[instance.AppDomain].Count == 0) 350 if (m_DomainScripts[instance.AppDomain].Count == 0)
291 { 351 {
292 m_DomainScripts.Remove(instance.AppDomain); 352 m_DomainScripts.Remove(instance.AppDomain);
293 UnloadAppDomain(instance.AppDomain); 353 UnloadAppDomain(instance.AppDomain);
294 }
295 } 354 }
296 m_Scripts.Clear();
297 m_PrimObjects.Clear();
298 m_Assemblies.Clear();
299 m_DomainScripts.Clear();
300 } 355 }
356 lockScriptsForRead(false);
357 lockScriptsForWrite(true);
358 m_Scripts.Clear();
359 lockScriptsForWrite(false);
360 m_PrimObjects.Clear();
361 m_Assemblies.Clear();
362 m_DomainScripts.Clear();
363
301 lock (m_ScriptEngines) 364 lock (m_ScriptEngines)
302 { 365 {
303 m_ScriptEngines.Remove(this); 366 m_ScriptEngines.Remove(this);
@@ -356,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
356 419
357 List<IScriptInstance> instances = new List<IScriptInstance>(); 420 List<IScriptInstance> instances = new List<IScriptInstance>();
358 421
359 lock (m_Scripts) 422 lockScriptsForRead(true);
360 { 423 foreach (IScriptInstance instance in m_Scripts.Values)
361 foreach (IScriptInstance instance in m_Scripts.Values)
362 instances.Add(instance); 424 instances.Add(instance);
363 } 425 lockScriptsForRead(false);
364 426
365 foreach (IScriptInstance i in instances) 427 foreach (IScriptInstance i in instances)
366 { 428 {
367 string assembly = String.Empty; 429 string assembly = String.Empty;
368 430
369 lock (m_Scripts) 431
370 {
371 if (!m_Assemblies.ContainsKey(i.AssetID)) 432 if (!m_Assemblies.ContainsKey(i.AssetID))
372 continue; 433 continue;
373 assembly = m_Assemblies[i.AssetID]; 434 assembly = m_Assemblies[i.AssetID];
374 } 435
375 436
376 i.SaveState(assembly); 437 i.SaveState(assembly);
377 } 438 }
@@ -673,172 +734,183 @@ namespace OpenSim.Region.ScriptEngine.XEngine
673 return false; 734 return false;
674 } 735 }
675 736
676 lock (m_Scripts) 737
738
739 ScriptInstance instance = null;
740 // Create the object record
741 lockScriptsForRead(true);
742 if ((!m_Scripts.ContainsKey(itemID)) ||
743 (m_Scripts[itemID].AssetID != assetID))
677 { 744 {
678 ScriptInstance instance = null; 745 lockScriptsForRead(false);
679 // Create the object record
680 746
681 if ((!m_Scripts.ContainsKey(itemID)) || 747 UUID appDomain = assetID;
682 (m_Scripts[itemID].AssetID != assetID))
683 {
684 UUID appDomain = assetID;
685 748
686 if (part.ParentGroup.IsAttachment) 749 if (part.ParentGroup.IsAttachment)
687 appDomain = part.ParentGroup.RootPart.UUID; 750 appDomain = part.ParentGroup.RootPart.UUID;
688 751
689 if (!m_AppDomains.ContainsKey(appDomain)) 752 if (!m_AppDomains.ContainsKey(appDomain))
753 {
754 try
690 { 755 {
691 try 756 AppDomainSetup appSetup = new AppDomainSetup();
692 { 757 // appSetup.ApplicationBase = Path.Combine(
693 AppDomainSetup appSetup = new AppDomainSetup(); 758 // "ScriptEngines",
694// appSetup.ApplicationBase = Path.Combine( 759 // m_Scene.RegionInfo.RegionID.ToString());
695// "ScriptEngines", 760
696// m_Scene.RegionInfo.RegionID.ToString()); 761 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
697 762 Evidence evidence = new Evidence(baseEvidence);
698 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 763
699 Evidence evidence = new Evidence(baseEvidence); 764 AppDomain sandbox;
700 765 if (m_AppDomainLoading)
701 AppDomain sandbox; 766 sandbox = AppDomain.CreateDomain(
702 if (m_AppDomainLoading) 767 m_Scene.RegionInfo.RegionID.ToString(),
703 sandbox = AppDomain.CreateDomain( 768 evidence, appSetup);
704 m_Scene.RegionInfo.RegionID.ToString(), 769 else
705 evidence, appSetup); 770 sandbox = AppDomain.CurrentDomain;
706 else 771
707 sandbox = AppDomain.CurrentDomain; 772 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
708 773 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
709 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 774 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
710 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 775 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
711 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 776 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
712 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 777 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
713 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 778 //sandbox.SetAppDomainPolicy(sandboxPolicy);
714 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 779
715 //sandbox.SetAppDomainPolicy(sandboxPolicy); 780 m_AppDomains[appDomain] = sandbox;
716 781
717 m_AppDomains[appDomain] = sandbox; 782 m_AppDomains[appDomain].AssemblyResolve +=
718 783 new ResolveEventHandler(
719 m_AppDomains[appDomain].AssemblyResolve += 784 AssemblyResolver.OnAssemblyResolve);
720 new ResolveEventHandler( 785 m_DomainScripts[appDomain] = new List<UUID>();
721 AssemblyResolver.OnAssemblyResolve);
722 m_DomainScripts[appDomain] = new List<UUID>();
723 }
724 catch (Exception e)
725 {
726 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
727 m_ScriptErrorMessage += "Exception creating app domain:\n";
728 m_ScriptFailCount++;
729 lock (m_AddingAssemblies)
730 {
731 m_AddingAssemblies[assembly]--;
732 }
733 return false;
734 }
735 } 786 }
736 m_DomainScripts[appDomain].Add(itemID); 787 catch (Exception e)
737
738 instance = new ScriptInstance(this, part,
739 itemID, assetID, assembly,
740 m_AppDomains[appDomain],
741 part.ParentGroup.RootPart.Name,
742 item.Name, startParam, postOnRez,
743 stateSource, m_MaxScriptQueue);
744
745 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
746 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
747
748 if (presence != null)
749 { 788 {
750 ShowScriptSaveResponse(item.OwnerID, 789 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
751 assetID, "Compile successful", true); 790 m_ScriptErrorMessage += "Exception creating app domain:\n";
791 m_ScriptFailCount++;
792 lock (m_AddingAssemblies)
793 {
794 m_AddingAssemblies[assembly]--;
795 }
796 return false;
752 } 797 }
798 }
799 m_DomainScripts[appDomain].Add(itemID);
753 800
754 instance.AppDomain = appDomain; 801 instance = new ScriptInstance(this, part,
755 instance.LineMap = linemap; 802 itemID, assetID, assembly,
803 m_AppDomains[appDomain],
804 part.ParentGroup.RootPart.Name,
805 item.Name, startParam, postOnRez,
806 stateSource, m_MaxScriptQueue);
756 807
757 m_Scripts[itemID] = instance; 808 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
758 } 809 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
759 810
760 lock (m_PrimObjects) 811 if (presence != null)
761 { 812 {
762 if (!m_PrimObjects.ContainsKey(localID)) 813 ShowScriptSaveResponse(item.OwnerID,
763 m_PrimObjects[localID] = new List<UUID>(); 814 assetID, "Compile successful", true);
815 }
764 816
765 if (!m_PrimObjects[localID].Contains(itemID)) 817 instance.AppDomain = appDomain;
766 m_PrimObjects[localID].Add(itemID); 818 instance.LineMap = linemap;
819 lockScriptsForWrite(true);
820 m_Scripts[itemID] = instance;
821 lockScriptsForWrite(false);
822 }
823 else
824 {
825 lockScriptsForRead(false);
826 }
827 lock (m_PrimObjects)
828 {
829 if (!m_PrimObjects.ContainsKey(localID))
830 m_PrimObjects[localID] = new List<UUID>();
767 831
768 } 832 if (!m_PrimObjects[localID].Contains(itemID))
833 m_PrimObjects[localID].Add(itemID);
769 834
770 if (!m_Assemblies.ContainsKey(assetID)) 835 }
771 m_Assemblies[assetID] = assembly;
772 836
773 lock (m_AddingAssemblies) 837 if (!m_Assemblies.ContainsKey(assetID))
774 { 838 m_Assemblies[assetID] = assembly;
775 m_AddingAssemblies[assembly]--;
776 }
777 839
778 if (instance!=null) 840 lock (m_AddingAssemblies)
779 instance.Init(); 841 {
842 m_AddingAssemblies[assembly]--;
780 } 843 }
844
845 if (instance!=null)
846 instance.Init();
847
781 return true; 848 return true;
782 } 849 }
783 850
784 public void OnRemoveScript(uint localID, UUID itemID) 851 public void OnRemoveScript(uint localID, UUID itemID)
785 { 852 {
786 lock (m_Scripts) 853 lockScriptsForRead(true);
854 // Do we even have it?
855 if (!m_Scripts.ContainsKey(itemID))
787 { 856 {
788 // Do we even have it? 857 lockScriptsForRead(false);
789 if (!m_Scripts.ContainsKey(itemID)) 858 return;
790 return; 859 }
860
791 861
792 IScriptInstance instance=m_Scripts[itemID]; 862 IScriptInstance instance=m_Scripts[itemID];
793 m_Scripts.Remove(itemID); 863 lockScriptsForRead(false);
864 lockScriptsForWrite(true);
865 m_Scripts.Remove(itemID);
866 lockScriptsForWrite(false);
867 instance.ClearQueue();
868 instance.Stop(0);
794 869
795 instance.ClearQueue(); 870 SceneObjectPart part =
796 instance.Stop(0); 871 m_Scene.GetSceneObjectPart(localID);
797 872
798 SceneObjectPart part = 873 if (part != null)
799 m_Scene.GetSceneObjectPart(localID); 874 part.RemoveScriptEvents(itemID);
800
801 if (part != null)
802 part.RemoveScriptEvents(itemID);
803 875
804// bool objectRemoved = false; 876// bool objectRemoved = false;
805 877
806 lock (m_PrimObjects) 878 lock (m_PrimObjects)
879 {
880 // Remove the script from it's prim
881 if (m_PrimObjects.ContainsKey(localID))
807 { 882 {
808 // Remove the script from it's prim 883 // Remove inventory item record
809 if (m_PrimObjects.ContainsKey(localID)) 884 if (m_PrimObjects[localID].Contains(itemID))
810 { 885 m_PrimObjects[localID].Remove(itemID);
811 // Remove inventory item record
812 if (m_PrimObjects[localID].Contains(itemID))
813 m_PrimObjects[localID].Remove(itemID);
814 886
815 // If there are no more scripts, remove prim 887 // If there are no more scripts, remove prim
816 if (m_PrimObjects[localID].Count == 0) 888 if (m_PrimObjects[localID].Count == 0)
817 { 889 {
818 m_PrimObjects.Remove(localID); 890 m_PrimObjects.Remove(localID);
819// objectRemoved = true; 891// objectRemoved = true;
820 }
821 } 892 }
822 } 893 }
894 }
823 895
824 instance.RemoveState(); 896 instance.RemoveState();
825 instance.DestroyScriptInstance(); 897 instance.DestroyScriptInstance();
826 898
827 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 899 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
828 if (m_DomainScripts[instance.AppDomain].Count == 0) 900 if (m_DomainScripts[instance.AppDomain].Count == 0)
829 { 901 {
830 m_DomainScripts.Remove(instance.AppDomain); 902 m_DomainScripts.Remove(instance.AppDomain);
831 UnloadAppDomain(instance.AppDomain); 903 UnloadAppDomain(instance.AppDomain);
832 } 904 }
833 905
834 instance = null; 906 instance = null;
835 907
836 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 908 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
837 if (handlerObjectRemoved != null) 909 if (handlerObjectRemoved != null)
838 handlerObjectRemoved(part.UUID); 910 handlerObjectRemoved(part.UUID);
839 911
840 CleanAssemblies(); 912 CleanAssemblies();
841 } 913
842 914
843 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 915 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
844 if (handlerScriptRemoved != null) 916 if (handlerScriptRemoved != null)
@@ -1091,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1091 private IScriptInstance GetInstance(UUID itemID) 1163 private IScriptInstance GetInstance(UUID itemID)
1092 { 1164 {
1093 IScriptInstance instance; 1165 IScriptInstance instance;
1094 lock (m_Scripts) 1166 lockScriptsForRead(true);
1167 if (!m_Scripts.ContainsKey(itemID))
1095 { 1168 {
1096 if (!m_Scripts.ContainsKey(itemID)) 1169 lockScriptsForRead(false);
1097 return null; 1170 return null;
1098 instance = m_Scripts[itemID];
1099 } 1171 }
1172 instance = m_Scripts[itemID];
1173 lockScriptsForRead(false);
1100 return instance; 1174 return instance;
1101 } 1175 }
1102 1176
@@ -1200,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1200 { 1274 {
1201 List<IScriptInstance> instances = new List<IScriptInstance>(); 1275 List<IScriptInstance> instances = new List<IScriptInstance>();
1202 1276
1203 lock (m_Scripts) 1277 lockScriptsForRead(true);
1204 { 1278 foreach (IScriptInstance instance in m_Scripts.Values)
1205 foreach (IScriptInstance instance in m_Scripts.Values)
1206 instances.Add(instance); 1279 instances.Add(instance);
1207 } 1280 lockScriptsForRead(false);
1208 1281
1209 foreach (IScriptInstance i in instances) 1282 foreach (IScriptInstance i in instances)
1210 { 1283 {