diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 362 |
1 files changed, 230 insertions, 132 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index f11987e..084ef48 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -28,6 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Diagnostics; //for [DebuggerNonUserCode] | ||
31 | using System.Globalization; | 32 | using System.Globalization; |
32 | using System.IO; | 33 | using System.IO; |
33 | using System.Reflection; | 34 | using System.Reflection; |
@@ -109,6 +110,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
109 | private Dictionary<UUID, IScriptInstance> m_Scripts = | 110 | private Dictionary<UUID, IScriptInstance> m_Scripts = |
110 | new Dictionary<UUID, IScriptInstance>(); | 111 | new Dictionary<UUID, IScriptInstance>(); |
111 | 112 | ||
113 | private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); | ||
114 | |||
112 | // Maps the asset ID to the assembly | 115 | // Maps the asset ID to the assembly |
113 | 116 | ||
114 | private Dictionary<UUID, string> m_Assemblies = | 117 | private Dictionary<UUID, string> m_Assemblies = |
@@ -131,6 +134,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
131 | IWorkItemResult m_CurrentCompile = null; | 134 | IWorkItemResult m_CurrentCompile = null; |
132 | private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); | 135 | private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); |
133 | 136 | ||
137 | private void lockScriptsForRead(bool locked) | ||
138 | { | ||
139 | if (locked) | ||
140 | { | ||
141 | if (m_scriptsLock.RecursiveReadCount > 0) | ||
142 | { | ||
143 | 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."); | ||
144 | m_scriptsLock.ExitReadLock(); | ||
145 | } | ||
146 | if (m_scriptsLock.RecursiveWriteCount > 0) | ||
147 | { | ||
148 | m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
149 | m_scriptsLock.ExitWriteLock(); | ||
150 | } | ||
151 | |||
152 | while (!m_scriptsLock.TryEnterReadLock(60000)) | ||
153 | { | ||
154 | 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."); | ||
155 | if (m_scriptsLock.IsWriteLockHeld) | ||
156 | { | ||
157 | m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | else | ||
162 | { | ||
163 | if (m_scriptsLock.RecursiveReadCount > 0) | ||
164 | { | ||
165 | m_scriptsLock.ExitReadLock(); | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | private void lockScriptsForWrite(bool locked) | ||
170 | { | ||
171 | if (locked) | ||
172 | { | ||
173 | if (m_scriptsLock.RecursiveReadCount > 0) | ||
174 | { | ||
175 | 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."); | ||
176 | m_scriptsLock.ExitReadLock(); | ||
177 | } | ||
178 | if (m_scriptsLock.RecursiveWriteCount > 0) | ||
179 | { | ||
180 | m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed."); | ||
181 | m_scriptsLock.ExitWriteLock(); | ||
182 | } | ||
183 | |||
184 | while (!m_scriptsLock.TryEnterWriteLock(60000)) | ||
185 | { | ||
186 | 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."); | ||
187 | if (m_scriptsLock.IsWriteLockHeld) | ||
188 | { | ||
189 | m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | else | ||
194 | { | ||
195 | if (m_scriptsLock.RecursiveWriteCount > 0) | ||
196 | { | ||
197 | m_scriptsLock.ExitWriteLock(); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
134 | public string ScriptEngineName | 202 | public string ScriptEngineName |
135 | { | 203 | { |
136 | get { return "XEngine"; } | 204 | get { return "XEngine"; } |
@@ -501,44 +569,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
501 | { | 569 | { |
502 | if (!m_Enabled) | 570 | if (!m_Enabled) |
503 | return; | 571 | return; |
504 | 572 | lockScriptsForRead(true); | |
505 | lock (m_Scripts) | 573 | foreach (IScriptInstance instance in m_Scripts.Values) |
506 | { | 574 | { |
507 | m_log.InfoFormat( | 575 | // Force a final state save |
508 | "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); | 576 | // |
509 | 577 | if (m_Assemblies.ContainsKey(instance.AssetID)) | |
510 | foreach (IScriptInstance instance in m_Scripts.Values) | ||
511 | { | 578 | { |
512 | // Force a final state save | 579 | string assembly = m_Assemblies[instance.AssetID]; |
513 | // | 580 | instance.SaveState(assembly); |
514 | if (m_Assemblies.ContainsKey(instance.AssetID)) | 581 | } |
515 | { | ||
516 | string assembly = m_Assemblies[instance.AssetID]; | ||
517 | instance.SaveState(assembly); | ||
518 | } | ||
519 | 582 | ||
520 | // Clear the event queue and abort the instance thread | 583 | // Clear the event queue and abort the instance thread |
521 | // | 584 | // |
522 | instance.ClearQueue(); | 585 | instance.ClearQueue(); |
523 | instance.Stop(0); | 586 | instance.Stop(0); |
524 | 587 | ||
525 | // Release events, timer, etc | 588 | // Release events, timer, etc |
526 | // | 589 | // |
527 | instance.DestroyScriptInstance(); | 590 | instance.DestroyScriptInstance(); |
528 | 591 | ||
529 | // Unload scripts and app domains. | 592 | // Unload scripts and app domains |
530 | // Must be done explicitly because they have infinite | 593 | // Must be done explicitly because they have infinite |
531 | // lifetime. | 594 | // lifetime |
532 | // However, don't bother to do this if the simulator is shutting | 595 | // |
533 | // down since it takes a long time with many scripts. | 596 | if (!m_SimulatorShuttingDown) |
534 | if (!m_SimulatorShuttingDown) | 597 | { |
598 | m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); | ||
599 | if (m_DomainScripts[instance.AppDomain].Count == 0) | ||
535 | { | 600 | { |
536 | m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); | 601 | m_DomainScripts.Remove(instance.AppDomain); |
537 | if (m_DomainScripts[instance.AppDomain].Count == 0) | 602 | UnloadAppDomain(instance.AppDomain); |
538 | { | ||
539 | m_DomainScripts.Remove(instance.AppDomain); | ||
540 | UnloadAppDomain(instance.AppDomain); | ||
541 | } | ||
542 | } | 603 | } |
543 | } | 604 | } |
544 | 605 | ||
@@ -547,6 +608,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
547 | m_Assemblies.Clear(); | 608 | m_Assemblies.Clear(); |
548 | m_DomainScripts.Clear(); | 609 | m_DomainScripts.Clear(); |
549 | } | 610 | } |
611 | lockScriptsForRead(false); | ||
612 | lockScriptsForWrite(true); | ||
613 | m_Scripts.Clear(); | ||
614 | lockScriptsForWrite(false); | ||
615 | m_PrimObjects.Clear(); | ||
616 | m_Assemblies.Clear(); | ||
617 | m_DomainScripts.Clear(); | ||
618 | |||
550 | lock (m_ScriptEngines) | 619 | lock (m_ScriptEngines) |
551 | { | 620 | { |
552 | m_ScriptEngines.Remove(this); | 621 | m_ScriptEngines.Remove(this); |
@@ -611,22 +680,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
611 | 680 | ||
612 | List<IScriptInstance> instances = new List<IScriptInstance>(); | 681 | List<IScriptInstance> instances = new List<IScriptInstance>(); |
613 | 682 | ||
614 | lock (m_Scripts) | 683 | lockScriptsForRead(true); |
615 | { | 684 | foreach (IScriptInstance instance in m_Scripts.Values) |
616 | foreach (IScriptInstance instance in m_Scripts.Values) | ||
617 | instances.Add(instance); | 685 | instances.Add(instance); |
618 | } | 686 | lockScriptsForRead(false); |
619 | 687 | ||
620 | foreach (IScriptInstance i in instances) | 688 | foreach (IScriptInstance i in instances) |
621 | { | 689 | { |
622 | string assembly = String.Empty; | 690 | string assembly = String.Empty; |
623 | 691 | ||
624 | lock (m_Scripts) | 692 | |
625 | { | ||
626 | if (!m_Assemblies.ContainsKey(i.AssetID)) | 693 | if (!m_Assemblies.ContainsKey(i.AssetID)) |
627 | continue; | 694 | continue; |
628 | assembly = m_Assemblies[i.AssetID]; | 695 | assembly = m_Assemblies[i.AssetID]; |
629 | } | 696 | |
630 | 697 | ||
631 | i.SaveState(assembly); | 698 | i.SaveState(assembly); |
632 | } | 699 | } |
@@ -960,92 +1027,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
960 | } | 1027 | } |
961 | 1028 | ||
962 | ScriptInstance instance = null; | 1029 | ScriptInstance instance = null; |
963 | lock (m_Scripts) | 1030 | // Create the object record |
1031 | lockScriptsForRead(true); | ||
1032 | if ((!m_Scripts.ContainsKey(itemID)) || | ||
1033 | (m_Scripts[itemID].AssetID != assetID)) | ||
964 | { | 1034 | { |
965 | // Create the object record | 1035 | lockScriptsForRead(false); |
966 | 1036 | ||
967 | if ((!m_Scripts.ContainsKey(itemID)) || | 1037 | UUID appDomain = assetID; |
968 | (m_Scripts[itemID].AssetID != assetID)) | ||
969 | { | ||
970 | UUID appDomain = assetID; | ||
971 | 1038 | ||
972 | if (part.ParentGroup.IsAttachment) | 1039 | if (part.ParentGroup.IsAttachment) |
973 | appDomain = part.ParentGroup.RootPart.UUID; | 1040 | appDomain = part.ParentGroup.RootPart.UUID; |
974 | 1041 | ||
975 | if (!m_AppDomains.ContainsKey(appDomain)) | 1042 | if (!m_AppDomains.ContainsKey(appDomain)) |
1043 | { | ||
1044 | try | ||
976 | { | 1045 | { |
977 | try | 1046 | AppDomainSetup appSetup = new AppDomainSetup(); |
978 | { | 1047 | appSetup.PrivateBinPath = Path.Combine( |
979 | AppDomainSetup appSetup = new AppDomainSetup(); | 1048 | m_ScriptEnginesPath, |
980 | appSetup.PrivateBinPath = Path.Combine( | 1049 | m_Scene.RegionInfo.RegionID.ToString()); |
981 | m_ScriptEnginesPath, | 1050 | |
982 | m_Scene.RegionInfo.RegionID.ToString()); | 1051 | Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; |
983 | 1052 | Evidence evidence = new Evidence(baseEvidence); | |
984 | Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; | 1053 | |
985 | Evidence evidence = new Evidence(baseEvidence); | 1054 | AppDomain sandbox; |
986 | 1055 | if (m_AppDomainLoading) | |
987 | AppDomain sandbox; | 1056 | sandbox = AppDomain.CreateDomain( |
988 | if (m_AppDomainLoading) | 1057 | m_Scene.RegionInfo.RegionID.ToString(), |
989 | sandbox = AppDomain.CreateDomain( | 1058 | evidence, appSetup); |
990 | m_Scene.RegionInfo.RegionID.ToString(), | 1059 | else |
991 | evidence, appSetup); | 1060 | sandbox = AppDomain.CurrentDomain; |
992 | else | 1061 | |
993 | sandbox = AppDomain.CurrentDomain; | 1062 | //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); |
994 | 1063 | //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); | |
995 | //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); | 1064 | //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); |
996 | //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); | 1065 | //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); |
997 | //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); | 1066 | //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); |
998 | //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); | 1067 | //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; |
999 | //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); | 1068 | //sandbox.SetAppDomainPolicy(sandboxPolicy); |
1000 | //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; | 1069 | |
1001 | //sandbox.SetAppDomainPolicy(sandboxPolicy); | 1070 | m_AppDomains[appDomain] = sandbox; |
1002 | 1071 | ||
1003 | m_AppDomains[appDomain] = sandbox; | 1072 | m_AppDomains[appDomain].AssemblyResolve += |
1004 | 1073 | new ResolveEventHandler( | |
1005 | m_AppDomains[appDomain].AssemblyResolve += | 1074 | AssemblyResolver.OnAssemblyResolve); |
1006 | new ResolveEventHandler( | 1075 | m_DomainScripts[appDomain] = new List<UUID>(); |
1007 | AssemblyResolver.OnAssemblyResolve); | 1076 | } |
1008 | m_DomainScripts[appDomain] = new List<UUID>(); | 1077 | catch (Exception e) |
1009 | } | 1078 | { |
1010 | catch (Exception e) | 1079 | m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); |
1080 | m_ScriptErrorMessage += "Exception creating app domain:\n"; | ||
1081 | m_ScriptFailCount++; | ||
1082 | lock (m_AddingAssemblies) | ||
1011 | { | 1083 | { |
1012 | m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); | 1084 | m_AddingAssemblies[assembly]--; |
1013 | m_ScriptErrorMessage += "Exception creating app domain:\n"; | ||
1014 | m_ScriptFailCount++; | ||
1015 | lock (m_AddingAssemblies) | ||
1016 | { | ||
1017 | m_AddingAssemblies[assembly]--; | ||
1018 | } | ||
1019 | return false; | ||
1020 | } | 1085 | } |
1086 | return false; | ||
1021 | } | 1087 | } |
1022 | m_DomainScripts[appDomain].Add(itemID); | 1088 | } |
1023 | 1089 | m_DomainScripts[appDomain].Add(itemID); | |
1024 | instance = new ScriptInstance(this, part, | 1090 | |
1025 | itemID, assetID, assembly, | 1091 | instance = new ScriptInstance(this, part, |
1026 | m_AppDomains[appDomain], | 1092 | itemID, assetID, assembly, |
1027 | part.ParentGroup.RootPart.Name, | 1093 | m_AppDomains[appDomain], |
1028 | item.Name, startParam, postOnRez, | 1094 | part.ParentGroup.RootPart.Name, |
1029 | stateSource, m_MaxScriptQueue); | 1095 | item.Name, startParam, postOnRez, |
1030 | 1096 | stateSource, m_MaxScriptQueue); | |
1031 | m_log.DebugFormat( | 1097 | |
1032 | "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", | 1098 | m_log.DebugFormat( |
1033 | part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, | 1099 | "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", |
1100 | part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, | ||
1034 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); | 1101 | part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); |
1035 | 1102 | ||
1036 | if (presence != null) | 1103 | if (presence != null) |
1037 | { | 1104 | { |
1038 | ShowScriptSaveResponse(item.OwnerID, | 1105 | ShowScriptSaveResponse(item.OwnerID, |
1039 | assetID, "Compile successful", true); | 1106 | assetID, "Compile successful", true); |
1040 | } | ||
1041 | |||
1042 | instance.AppDomain = appDomain; | ||
1043 | instance.LineMap = linemap; | ||
1044 | |||
1045 | m_Scripts[itemID] = instance; | ||
1046 | } | 1107 | } |
1047 | } | ||
1048 | 1108 | ||
1109 | instance.AppDomain = appDomain; | ||
1110 | instance.LineMap = linemap; | ||
1111 | lockScriptsForWrite(true); | ||
1112 | m_Scripts[itemID] = instance; | ||
1113 | lockScriptsForWrite(false); | ||
1114 | } | ||
1115 | else | ||
1116 | { | ||
1117 | lockScriptsForRead(false); | ||
1118 | } | ||
1049 | lock (m_PrimObjects) | 1119 | lock (m_PrimObjects) |
1050 | { | 1120 | { |
1051 | if (!m_PrimObjects.ContainsKey(localID)) | 1121 | if (!m_PrimObjects.ContainsKey(localID)) |
@@ -1064,9 +1134,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1064 | m_AddingAssemblies[assembly]--; | 1134 | m_AddingAssemblies[assembly]--; |
1065 | } | 1135 | } |
1066 | 1136 | ||
1067 | if (instance != null) | 1137 | if (instance!=null) |
1068 | instance.Init(); | 1138 | instance.Init(); |
1069 | 1139 | ||
1070 | return true; | 1140 | return true; |
1071 | } | 1141 | } |
1072 | 1142 | ||
@@ -1079,20 +1149,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1079 | m_CompileDict.Remove(itemID); | 1149 | m_CompileDict.Remove(itemID); |
1080 | } | 1150 | } |
1081 | 1151 | ||
1082 | IScriptInstance instance = null; | 1152 | lockScriptsForRead(true); |
1083 | 1153 | // Do we even have it? | |
1084 | lock (m_Scripts) | 1154 | if (!m_Scripts.ContainsKey(itemID)) |
1085 | { | 1155 | { |
1086 | // Do we even have it? | 1156 | // Do we even have it? |
1087 | if (!m_Scripts.ContainsKey(itemID)) | 1157 | if (!m_Scripts.ContainsKey(itemID)) |
1088 | return; | 1158 | return; |
1089 | 1159 | ||
1090 | instance = m_Scripts[itemID]; | 1160 | lockScriptsForRead(false); |
1161 | lockScriptsForWrite(true); | ||
1091 | m_Scripts.Remove(itemID); | 1162 | m_Scripts.Remove(itemID); |
1163 | lockScriptsForWrite(false); | ||
1164 | |||
1165 | return; | ||
1092 | } | 1166 | } |
1167 | |||
1093 | 1168 | ||
1169 | IScriptInstance instance=m_Scripts[itemID]; | ||
1170 | lockScriptsForRead(false); | ||
1171 | lockScriptsForWrite(true); | ||
1172 | m_Scripts.Remove(itemID); | ||
1173 | lockScriptsForWrite(false); | ||
1094 | instance.ClearQueue(); | 1174 | instance.ClearQueue(); |
1095 | instance.Stop(0); | 1175 | instance.Stop(0); |
1176 | |||
1096 | // bool objectRemoved = false; | 1177 | // bool objectRemoved = false; |
1097 | 1178 | ||
1098 | lock (m_PrimObjects) | 1179 | lock (m_PrimObjects) |
@@ -1128,11 +1209,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1128 | ObjectRemoved handlerObjectRemoved = OnObjectRemoved; | 1209 | ObjectRemoved handlerObjectRemoved = OnObjectRemoved; |
1129 | if (handlerObjectRemoved != null) | 1210 | if (handlerObjectRemoved != null) |
1130 | { | 1211 | { |
1131 | SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); | 1212 | SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); |
1132 | handlerObjectRemoved(part.UUID); | 1213 | handlerObjectRemoved(part.UUID); |
1133 | } | 1214 | } |
1134 | 1215 | ||
1135 | 1216 | CleanAssemblies(); | |
1217 | |||
1136 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; | 1218 | ScriptRemoved handlerScriptRemoved = OnScriptRemoved; |
1137 | if (handlerScriptRemoved != null) | 1219 | if (handlerScriptRemoved != null) |
1138 | handlerScriptRemoved(itemID); | 1220 | handlerScriptRemoved(itemID); |
@@ -1274,7 +1356,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1274 | return false; | 1356 | return false; |
1275 | 1357 | ||
1276 | uuids = m_PrimObjects[localID]; | 1358 | uuids = m_PrimObjects[localID]; |
1277 | } | 1359 | |
1278 | 1360 | ||
1279 | foreach (UUID itemID in uuids) | 1361 | foreach (UUID itemID in uuids) |
1280 | { | 1362 | { |
@@ -1292,6 +1374,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1292 | result = true; | 1374 | result = true; |
1293 | } | 1375 | } |
1294 | } | 1376 | } |
1377 | } | ||
1295 | 1378 | ||
1296 | return result; | 1379 | return result; |
1297 | } | 1380 | } |
@@ -1391,12 +1474,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1391 | private IScriptInstance GetInstance(UUID itemID) | 1474 | private IScriptInstance GetInstance(UUID itemID) |
1392 | { | 1475 | { |
1393 | IScriptInstance instance; | 1476 | IScriptInstance instance; |
1394 | lock (m_Scripts) | 1477 | lockScriptsForRead(true); |
1478 | if (!m_Scripts.ContainsKey(itemID)) | ||
1395 | { | 1479 | { |
1396 | if (!m_Scripts.ContainsKey(itemID)) | 1480 | lockScriptsForRead(false); |
1397 | return null; | 1481 | return null; |
1398 | instance = m_Scripts[itemID]; | ||
1399 | } | 1482 | } |
1483 | instance = m_Scripts[itemID]; | ||
1484 | lockScriptsForRead(false); | ||
1400 | return instance; | 1485 | return instance; |
1401 | } | 1486 | } |
1402 | 1487 | ||
@@ -1420,6 +1505,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1420 | return false; | 1505 | return false; |
1421 | } | 1506 | } |
1422 | 1507 | ||
1508 | [DebuggerNonUserCode] | ||
1423 | public void ApiResetScript(UUID itemID) | 1509 | public void ApiResetScript(UUID itemID) |
1424 | { | 1510 | { |
1425 | IScriptInstance instance = GetInstance(itemID); | 1511 | IScriptInstance instance = GetInstance(itemID); |
@@ -1471,6 +1557,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1471 | return UUID.Zero; | 1557 | return UUID.Zero; |
1472 | } | 1558 | } |
1473 | 1559 | ||
1560 | [DebuggerNonUserCode] | ||
1474 | public void SetState(UUID itemID, string newState) | 1561 | public void SetState(UUID itemID, string newState) |
1475 | { | 1562 | { |
1476 | IScriptInstance instance = GetInstance(itemID); | 1563 | IScriptInstance instance = GetInstance(itemID); |
@@ -1493,11 +1580,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1493 | 1580 | ||
1494 | List<IScriptInstance> instances = new List<IScriptInstance>(); | 1581 | List<IScriptInstance> instances = new List<IScriptInstance>(); |
1495 | 1582 | ||
1496 | lock (m_Scripts) | 1583 | lockScriptsForRead(true); |
1497 | { | 1584 | foreach (IScriptInstance instance in m_Scripts.Values) |
1498 | foreach (IScriptInstance instance in m_Scripts.Values) | ||
1499 | instances.Add(instance); | 1585 | instances.Add(instance); |
1500 | } | 1586 | lockScriptsForRead(false); |
1501 | 1587 | ||
1502 | foreach (IScriptInstance i in instances) | 1588 | foreach (IScriptInstance i in instances) |
1503 | { | 1589 | { |
@@ -1874,5 +1960,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1874 | if (instance != null) | 1960 | if (instance != null) |
1875 | instance.Resume(); | 1961 | instance.Resume(); |
1876 | } | 1962 | } |
1963 | |||
1964 | public bool HasScript(UUID itemID, out bool running) | ||
1965 | { | ||
1966 | running = true; | ||
1967 | |||
1968 | IScriptInstance instance = GetInstance(itemID); | ||
1969 | if (instance == null) | ||
1970 | return false; | ||
1971 | |||
1972 | running = instance.Running; | ||
1973 | return true; | ||
1974 | } | ||
1877 | } | 1975 | } |
1878 | } \ No newline at end of file | 1976 | } |