aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs362
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 @@
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;
@@ -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}