aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs364
1 files changed, 233 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 105d97d..ee5f519 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Globalization; 32using System.Globalization;
32using System.IO; 33using System.IO;
33using System.Reflection; 34using System.Reflection;
@@ -112,6 +113,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
112 private Dictionary<UUID, IScriptInstance> m_Scripts = 113 private Dictionary<UUID, IScriptInstance> m_Scripts =
113 new Dictionary<UUID, IScriptInstance>(); 114 new Dictionary<UUID, IScriptInstance>();
114 115
116 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
117
115 // Maps the asset ID to the assembly 118 // Maps the asset ID to the assembly
116 119
117 private Dictionary<UUID, string> m_Assemblies = 120 private Dictionary<UUID, string> m_Assemblies =
@@ -134,6 +137,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
134 IWorkItemResult m_CurrentCompile = null; 137 IWorkItemResult m_CurrentCompile = null;
135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 138 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
136 139
140 private void lockScriptsForRead(bool locked)
141 {
142 if (locked)
143 {
144 if (m_scriptsLock.RecursiveReadCount > 0)
145 {
146 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.");
147 m_scriptsLock.ExitReadLock();
148 }
149 if (m_scriptsLock.RecursiveWriteCount > 0)
150 {
151 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
152 m_scriptsLock.ExitWriteLock();
153 }
154
155 while (!m_scriptsLock.TryEnterReadLock(60000))
156 {
157 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.");
158 if (m_scriptsLock.IsWriteLockHeld)
159 {
160 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
161 }
162 }
163 }
164 else
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 m_scriptsLock.ExitReadLock();
169 }
170 }
171 }
172 private void lockScriptsForWrite(bool locked)
173 {
174 if (locked)
175 {
176 if (m_scriptsLock.RecursiveReadCount > 0)
177 {
178 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.");
179 m_scriptsLock.ExitReadLock();
180 }
181 if (m_scriptsLock.RecursiveWriteCount > 0)
182 {
183 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
184 m_scriptsLock.ExitWriteLock();
185 }
186
187 while (!m_scriptsLock.TryEnterWriteLock(60000))
188 {
189 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.");
190 if (m_scriptsLock.IsWriteLockHeld)
191 {
192 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
193 }
194 }
195 }
196 else
197 {
198 if (m_scriptsLock.RecursiveWriteCount > 0)
199 {
200 m_scriptsLock.ExitWriteLock();
201 }
202 }
203 }
204
137 public string ScriptEngineName 205 public string ScriptEngineName
138 { 206 {
139 get { return "XEngine"; } 207 get { return "XEngine"; }
@@ -522,44 +590,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
522 { 590 {
523 if (!m_Enabled) 591 if (!m_Enabled)
524 return; 592 return;
525 593 lockScriptsForRead(true);
526 lock (m_Scripts) 594 foreach (IScriptInstance instance in m_Scripts.Values)
527 { 595 {
528 m_log.InfoFormat( 596 // Force a final state save
529 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 597 //
530 598 if (m_Assemblies.ContainsKey(instance.AssetID))
531 foreach (IScriptInstance instance in m_Scripts.Values)
532 { 599 {
533 // Force a final state save 600 string assembly = m_Assemblies[instance.AssetID];
534 // 601 instance.SaveState(assembly);
535 if (m_Assemblies.ContainsKey(instance.AssetID)) 602 }
536 {
537 string assembly = m_Assemblies[instance.AssetID];
538 instance.SaveState(assembly);
539 }
540 603
541 // Clear the event queue and abort the instance thread 604 // Clear the event queue and abort the instance thread
542 // 605 //
543 instance.ClearQueue(); 606 instance.ClearQueue();
544 instance.Stop(0); 607 instance.Stop(0);
545 608
546 // Release events, timer, etc 609 // Release events, timer, etc
547 // 610 //
548 instance.DestroyScriptInstance(); 611 instance.DestroyScriptInstance();
549 612
550 // Unload scripts and app domains. 613 // Unload scripts and app domains
551 // Must be done explicitly because they have infinite 614 // Must be done explicitly because they have infinite
552 // lifetime. 615 // lifetime
553 // However, don't bother to do this if the simulator is shutting 616 //
554 // down since it takes a long time with many scripts. 617 if (!m_SimulatorShuttingDown)
555 if (!m_SimulatorShuttingDown) 618 {
619 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
620 if (m_DomainScripts[instance.AppDomain].Count == 0)
556 { 621 {
557 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 622 m_DomainScripts.Remove(instance.AppDomain);
558 if (m_DomainScripts[instance.AppDomain].Count == 0) 623 UnloadAppDomain(instance.AppDomain);
559 {
560 m_DomainScripts.Remove(instance.AppDomain);
561 UnloadAppDomain(instance.AppDomain);
562 }
563 } 624 }
564 } 625 }
565 626
@@ -568,6 +629,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
568 m_Assemblies.Clear(); 629 m_Assemblies.Clear();
569 m_DomainScripts.Clear(); 630 m_DomainScripts.Clear();
570 } 631 }
632 lockScriptsForRead(false);
633 lockScriptsForWrite(true);
634 m_Scripts.Clear();
635 lockScriptsForWrite(false);
636 m_PrimObjects.Clear();
637 m_Assemblies.Clear();
638 m_DomainScripts.Clear();
639
571 lock (m_ScriptEngines) 640 lock (m_ScriptEngines)
572 { 641 {
573 m_ScriptEngines.Remove(this); 642 m_ScriptEngines.Remove(this);
@@ -632,22 +701,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
632 701
633 List<IScriptInstance> instances = new List<IScriptInstance>(); 702 List<IScriptInstance> instances = new List<IScriptInstance>();
634 703
635 lock (m_Scripts) 704 lockScriptsForRead(true);
636 { 705 foreach (IScriptInstance instance in m_Scripts.Values)
637 foreach (IScriptInstance instance in m_Scripts.Values)
638 instances.Add(instance); 706 instances.Add(instance);
639 } 707 lockScriptsForRead(false);
640 708
641 foreach (IScriptInstance i in instances) 709 foreach (IScriptInstance i in instances)
642 { 710 {
643 string assembly = String.Empty; 711 string assembly = String.Empty;
644 712
645 lock (m_Scripts) 713
646 {
647 if (!m_Assemblies.ContainsKey(i.AssetID)) 714 if (!m_Assemblies.ContainsKey(i.AssetID))
648 continue; 715 continue;
649 assembly = m_Assemblies[i.AssetID]; 716 assembly = m_Assemblies[i.AssetID];
650 } 717
651 718
652 i.SaveState(assembly); 719 i.SaveState(assembly);
653 } 720 }
@@ -991,91 +1058,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
991 } 1058 }
992 1059
993 ScriptInstance instance = null; 1060 ScriptInstance instance = null;
994 lock (m_Scripts) 1061 // Create the object record
1062 lockScriptsForRead(true);
1063 if ((!m_Scripts.ContainsKey(itemID)) ||
1064 (m_Scripts[itemID].AssetID != assetID))
995 { 1065 {
996 // Create the object record 1066 lockScriptsForRead(false);
997 if ((!m_Scripts.ContainsKey(itemID)) ||
998 (m_Scripts[itemID].AssetID != assetID))
999 {
1000 UUID appDomain = assetID;
1001 1067
1002 if (part.ParentGroup.IsAttachment) 1068 UUID appDomain = assetID;
1003 appDomain = part.ParentGroup.RootPart.UUID;
1004 1069
1005 if (!m_AppDomains.ContainsKey(appDomain)) 1070 if (part.ParentGroup.IsAttachment)
1006 { 1071 appDomain = part.ParentGroup.RootPart.UUID;
1007 try
1008 {
1009 AppDomainSetup appSetup = new AppDomainSetup();
1010 appSetup.PrivateBinPath = Path.Combine(
1011 m_ScriptEnginesPath,
1012 m_Scene.RegionInfo.RegionID.ToString());
1013
1014 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1015 Evidence evidence = new Evidence(baseEvidence);
1016
1017 AppDomain sandbox;
1018 if (m_AppDomainLoading)
1019 sandbox = AppDomain.CreateDomain(
1020 m_Scene.RegionInfo.RegionID.ToString(),
1021 evidence, appSetup);
1022 else
1023 sandbox = AppDomain.CurrentDomain;
1024
1025 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1026 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1027 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1028 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1029 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1030 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1031 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1032
1033 m_AppDomains[appDomain] = sandbox;
1034 1072
1035 m_AppDomains[appDomain].AssemblyResolve += 1073 if (!m_AppDomains.ContainsKey(appDomain))
1036 new ResolveEventHandler( 1074 {
1037 AssemblyResolver.OnAssemblyResolve); 1075 try
1038 m_DomainScripts[appDomain] = new List<UUID>(); 1076 {
1039 } 1077 AppDomainSetup appSetup = new AppDomainSetup();
1040 catch (Exception e) 1078 appSetup.PrivateBinPath = Path.Combine(
1079 m_ScriptEnginesPath,
1080 m_Scene.RegionInfo.RegionID.ToString());
1081
1082 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1083 Evidence evidence = new Evidence(baseEvidence);
1084
1085 AppDomain sandbox;
1086 if (m_AppDomainLoading)
1087 sandbox = AppDomain.CreateDomain(
1088 m_Scene.RegionInfo.RegionID.ToString(),
1089 evidence, appSetup);
1090 else
1091 sandbox = AppDomain.CurrentDomain;
1092
1093 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1094 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1095 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1096 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1097 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1098 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1099 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1100
1101 m_AppDomains[appDomain] = sandbox;
1102
1103 m_AppDomains[appDomain].AssemblyResolve +=
1104 new ResolveEventHandler(
1105 AssemblyResolver.OnAssemblyResolve);
1106 m_DomainScripts[appDomain] = new List<UUID>();
1107 }
1108 catch (Exception e)
1109 {
1110 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1111 m_ScriptErrorMessage += "Exception creating app domain:\n";
1112 m_ScriptFailCount++;
1113 lock (m_AddingAssemblies)
1041 { 1114 {
1042 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1115 m_AddingAssemblies[assembly]--;
1043 m_ScriptErrorMessage += "Exception creating app domain:\n";
1044 m_ScriptFailCount++;
1045 lock (m_AddingAssemblies)
1046 {
1047 m_AddingAssemblies[assembly]--;
1048 }
1049 return false;
1050 } 1116 }
1117 return false;
1051 } 1118 }
1052 m_DomainScripts[appDomain].Add(itemID); 1119 }
1053 1120 m_DomainScripts[appDomain].Add(itemID);
1054 instance = new ScriptInstance(this, part, 1121
1055 itemID, assetID, assembly, 1122 instance = new ScriptInstance(this, part,
1056 m_AppDomains[appDomain], 1123 itemID, assetID, assembly,
1057 part.ParentGroup.RootPart.Name, 1124 m_AppDomains[appDomain],
1058 item.Name, startParam, postOnRez, 1125 part.ParentGroup.RootPart.Name,
1059 stateSource, m_MaxScriptQueue); 1126 item.Name, startParam, postOnRez,
1060 1127 stateSource, m_MaxScriptQueue);
1061 m_log.DebugFormat( 1128
1062 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1129 m_log.DebugFormat(
1063 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1130 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1131 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1064 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1132 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1065 1133
1066 if (presence != null) 1134 if (presence != null)
1067 { 1135 {
1068 ShowScriptSaveResponse(item.OwnerID, 1136 ShowScriptSaveResponse(item.OwnerID,
1069 assetID, "Compile successful", true); 1137 assetID, "Compile successful", true);
1070 }
1071
1072 instance.AppDomain = appDomain;
1073 instance.LineMap = linemap;
1074
1075 m_Scripts[itemID] = instance;
1076 } 1138 }
1077 }
1078 1139
1140 instance.AppDomain = appDomain;
1141 instance.LineMap = linemap;
1142 lockScriptsForWrite(true);
1143 m_Scripts[itemID] = instance;
1144 lockScriptsForWrite(false);
1145 }
1146 else
1147 {
1148 lockScriptsForRead(false);
1149 }
1079 lock (m_PrimObjects) 1150 lock (m_PrimObjects)
1080 { 1151 {
1081 if (!m_PrimObjects.ContainsKey(localID)) 1152 if (!m_PrimObjects.ContainsKey(localID))
@@ -1094,9 +1165,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1094 m_AddingAssemblies[assembly]--; 1165 m_AddingAssemblies[assembly]--;
1095 } 1166 }
1096 1167
1097 if (instance != null) 1168 if (instance!=null)
1098 instance.Init(); 1169 instance.Init();
1099 1170
1100 return true; 1171 return true;
1101 } 1172 }
1102 1173
@@ -1109,18 +1180,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1109 m_CompileDict.Remove(itemID); 1180 m_CompileDict.Remove(itemID);
1110 } 1181 }
1111 1182
1112 IScriptInstance instance = null; 1183 lockScriptsForRead(true);
1113 1184 // Do we even have it?
1114 lock (m_Scripts) 1185 if (!m_Scripts.ContainsKey(itemID))
1115 { 1186 {
1116 // Do we even have it? 1187 // Do we even have it?
1117 if (!m_Scripts.ContainsKey(itemID)) 1188 if (!m_Scripts.ContainsKey(itemID))
1118 return; 1189 return;
1119 1190
1120 instance = m_Scripts[itemID]; 1191 lockScriptsForRead(false);
1192 lockScriptsForWrite(true);
1121 m_Scripts.Remove(itemID); 1193 m_Scripts.Remove(itemID);
1194 lockScriptsForWrite(false);
1195
1196 return;
1122 } 1197 }
1198
1123 1199
1200 IScriptInstance instance=m_Scripts[itemID];
1201 lockScriptsForRead(false);
1202 lockScriptsForWrite(true);
1203 m_Scripts.Remove(itemID);
1204 lockScriptsForWrite(false);
1124 instance.ClearQueue(); 1205 instance.ClearQueue();
1125 1206
1126 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1207 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1159,8 +1240,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1159 1240
1160 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1241 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1161 if (handlerObjectRemoved != null) 1242 if (handlerObjectRemoved != null)
1162 handlerObjectRemoved(instance.ObjectID); 1243 {
1244 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1245 handlerObjectRemoved(part.UUID);
1246 }
1163 1247
1248 CleanAssemblies();
1249
1164 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1250 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1165 if (handlerScriptRemoved != null) 1251 if (handlerScriptRemoved != null)
1166 handlerScriptRemoved(itemID); 1252 handlerScriptRemoved(itemID);
@@ -1302,7 +1388,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1302 return false; 1388 return false;
1303 1389
1304 uuids = m_PrimObjects[localID]; 1390 uuids = m_PrimObjects[localID];
1305 } 1391
1306 1392
1307 foreach (UUID itemID in uuids) 1393 foreach (UUID itemID in uuids)
1308 { 1394 {
@@ -1320,6 +1406,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1320 result = true; 1406 result = true;
1321 } 1407 }
1322 } 1408 }
1409 }
1323 1410
1324 return result; 1411 return result;
1325 } 1412 }
@@ -1421,12 +1508,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1421 private IScriptInstance GetInstance(UUID itemID) 1508 private IScriptInstance GetInstance(UUID itemID)
1422 { 1509 {
1423 IScriptInstance instance; 1510 IScriptInstance instance;
1424 lock (m_Scripts) 1511 lockScriptsForRead(true);
1512 if (!m_Scripts.ContainsKey(itemID))
1425 { 1513 {
1426 if (!m_Scripts.ContainsKey(itemID)) 1514 lockScriptsForRead(false);
1427 return null; 1515 return null;
1428 instance = m_Scripts[itemID];
1429 } 1516 }
1517 instance = m_Scripts[itemID];
1518 lockScriptsForRead(false);
1430 return instance; 1519 return instance;
1431 } 1520 }
1432 1521
@@ -1450,6 +1539,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1450 return false; 1539 return false;
1451 } 1540 }
1452 1541
1542 [DebuggerNonUserCode]
1453 public void ApiResetScript(UUID itemID) 1543 public void ApiResetScript(UUID itemID)
1454 { 1544 {
1455 IScriptInstance instance = GetInstance(itemID); 1545 IScriptInstance instance = GetInstance(itemID);
@@ -1501,6 +1591,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1501 return UUID.Zero; 1591 return UUID.Zero;
1502 } 1592 }
1503 1593
1594 [DebuggerNonUserCode]
1504 public void SetState(UUID itemID, string newState) 1595 public void SetState(UUID itemID, string newState)
1505 { 1596 {
1506 IScriptInstance instance = GetInstance(itemID); 1597 IScriptInstance instance = GetInstance(itemID);
@@ -1523,11 +1614,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1523 1614
1524 List<IScriptInstance> instances = new List<IScriptInstance>(); 1615 List<IScriptInstance> instances = new List<IScriptInstance>();
1525 1616
1526 lock (m_Scripts) 1617 lockScriptsForRead(true);
1527 { 1618 foreach (IScriptInstance instance in m_Scripts.Values)
1528 foreach (IScriptInstance instance in m_Scripts.Values)
1529 instances.Add(instance); 1619 instances.Add(instance);
1530 } 1620 lockScriptsForRead(false);
1531 1621
1532 foreach (IScriptInstance i in instances) 1622 foreach (IScriptInstance i in instances)
1533 { 1623 {
@@ -1912,5 +2002,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1912// else 2002// else
1913// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2003// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1914 } 2004 }
2005
2006 public bool HasScript(UUID itemID, out bool running)
2007 {
2008 running = true;
2009
2010 IScriptInstance instance = GetInstance(itemID);
2011 if (instance == null)
2012 return false;
2013
2014 running = instance.Running;
2015 return true;
2016 }
1915 } 2017 }
1916} \ No newline at end of file 2018}