diff options
author | Tedd Hansen | 2007-08-25 15:31:47 +0000 |
---|---|---|
committer | Tedd Hansen | 2007-08-25 15:31:47 +0000 |
commit | 53be4774b32f6736373c1364c3bd659c977fbb4e (patch) | |
tree | c81bbc0d41b375bcc403c574da612d18b038c228 | |
parent | Hopefully fixed the bugs in primitives rotation editing (diff) | |
download | opensim-SC-53be4774b32f6736373c1364c3bd659c977fbb4e.zip opensim-SC-53be4774b32f6736373c1364c3bd659c977fbb4e.tar.gz opensim-SC-53be4774b32f6736373c1364c3bd659c977fbb4e.tar.bz2 opensim-SC-53be4774b32f6736373c1364c3bd659c977fbb4e.tar.xz |
Scripts no longer crash sim after 5 minutes (override InitializeLifetimeService). Loading/Unloading of scripts are now handled in separate thread so server is no delayed because of this. Each script is loaded into a single AppDomain (temporary test for script unload, eats ~15KB more memory for each script). Unload of scripts has been verified to free up memory.
7 files changed, 190 insertions, 60 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/Executor.cs b/OpenSim/Region/ScriptEngine/Common/Executor.cs index 148ae0f..cadd55c 100644 --- a/OpenSim/Region/ScriptEngine/Common/Executor.cs +++ b/OpenSim/Region/ScriptEngine/Common/Executor.cs | |||
@@ -2,34 +2,40 @@ using System; | |||
2 | using System.Collections.Generic; | 2 | using System.Collections.Generic; |
3 | using System.Text; | 3 | using System.Text; |
4 | using System.Reflection; | 4 | using System.Reflection; |
5 | using System.Runtime.Remoting.Lifetime; | ||
5 | 6 | ||
6 | namespace OpenSim.Region.ScriptEngine.Common | 7 | namespace OpenSim.Region.ScriptEngine.Common |
7 | { | 8 | { |
8 | public class Executor : MarshalByRefObject | 9 | public class Executor : MarshalByRefObject |
9 | { | 10 | { |
10 | /* TODO: | 11 | // Private instance for each script |
11 | * | ||
12 | * Needs to be common for all AppDomains - share memory too? | ||
13 | * Needs to have an instance in each AppDomain, and some way of referring it. | ||
14 | * Need to know what AppDomain a script is in so we know where to find our instance. | ||
15 | * | ||
16 | */ | ||
17 | 12 | ||
18 | private IScript m_Script; | 13 | private IScript m_Script; |
19 | private Dictionary<string, MethodInfo> Events = new Dictionary<string, MethodInfo>(); | 14 | private Dictionary<string, MethodInfo> Events = new Dictionary<string, MethodInfo>(); |
20 | private bool m_Running = true; | 15 | private bool m_Running = true; |
21 | 16 | //private List<IScript> Scripts = new List<IScript>(); | |
22 | 17 | ||
23 | public Executor(IScript Script) | 18 | public Executor(IScript Script) |
24 | { | 19 | { |
25 | m_Script = Script; | 20 | m_Script = Script; |
26 | |||
27 | } | 21 | } |
28 | 22 | ||
29 | public void StopScript() | 23 | // Object never expires |
24 | public override Object InitializeLifetimeService() | ||
30 | { | 25 | { |
31 | m_Running = false; | 26 | Console.WriteLine("Executor: InitializeLifetimeService()"); |
27 | // return null; | ||
28 | ILease lease = (ILease)base.InitializeLifetimeService(); | ||
29 | |||
30 | if (lease.CurrentState == LeaseState.Initial) | ||
31 | { | ||
32 | lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); | ||
33 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); | ||
34 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); | ||
35 | } | ||
36 | return lease; | ||
32 | } | 37 | } |
38 | |||
33 | public AppDomain GetAppDomain() | 39 | public AppDomain GetAppDomain() |
34 | { | 40 | { |
35 | return AppDomain.CurrentDomain; | 41 | return AppDomain.CurrentDomain; |
@@ -40,14 +46,6 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
40 | // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. | 46 | // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. |
41 | // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! | 47 | // Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead! |
42 | 48 | ||
43 | //foreach (MemberInfo mi in this.GetType().GetMembers()) | ||
44 | //{ | ||
45 | //if (mi.ToString().ToLower().Contains("default")) | ||
46 | //{ | ||
47 | // Console.WriteLine("Member found: " + mi.ToString()); | ||
48 | //} | ||
49 | //} | ||
50 | |||
51 | if (m_Running == false) | 49 | if (m_Running == false) |
52 | { | 50 | { |
53 | // Script is inactive, do not execute! | 51 | // Script is inactive, do not execute! |
@@ -97,6 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
97 | } | 95 | } |
98 | } | 96 | } |
99 | 97 | ||
98 | |||
99 | public void StopScript() | ||
100 | { | ||
101 | m_Running = false; | ||
102 | } | ||
103 | |||
104 | |||
100 | } | 105 | } |
101 | 106 | ||
102 | } | 107 | } |
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs index 3319783..63e1844 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs | |||
@@ -15,7 +15,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
15 | { | 15 | { |
16 | public class AppDomainManager | 16 | public class AppDomainManager |
17 | { | 17 | { |
18 | private int MaxScriptsPerAppDomain = 3; | 18 | private int MaxScriptsPerAppDomain = 1; |
19 | /// <summary> | 19 | /// <summary> |
20 | /// Internal list of all AppDomains | 20 | /// Internal list of all AppDomains |
21 | /// </summary> | 21 | /// </summary> |
@@ -59,7 +59,6 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
59 | private AppDomainStructure GetFreeAppDomain() | 59 | private AppDomainStructure GetFreeAppDomain() |
60 | { | 60 | { |
61 | Console.WriteLine("Finding free AppDomain"); | 61 | Console.WriteLine("Finding free AppDomain"); |
62 | FreeAppDomains(); // Outsite lock, has its own GetLock | ||
63 | lock (GetLock) | 62 | lock (GetLock) |
64 | { | 63 | { |
65 | // Current full? | 64 | // Current full? |
@@ -111,7 +110,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
111 | /// <summary> | 110 | /// <summary> |
112 | /// Unload appdomains that are full and have only dead scripts | 111 | /// Unload appdomains that are full and have only dead scripts |
113 | /// </summary> | 112 | /// </summary> |
114 | private void FreeAppDomains() | 113 | private void UnloadAppDomains() |
115 | { | 114 | { |
116 | lock (FreeLock) | 115 | lock (FreeLock) |
117 | { | 116 | { |
@@ -125,10 +124,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
125 | // Is number of unloaded bigger or equal to number of loaded? | 124 | // Is number of unloaded bigger or equal to number of loaded? |
126 | if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) | 125 | if (ads.ScriptsLoaded <= ads.ScriptsWaitingUnload) |
127 | { | 126 | { |
127 | Console.WriteLine("Found empty AppDomain, unloading"); | ||
128 | // Remove from internal list | 128 | // Remove from internal list |
129 | AppDomains.Remove(ads); | 129 | AppDomains.Remove(ads); |
130 | #if DEBUG | ||
131 | |||
132 | long m = GC.GetTotalMemory(true); | ||
133 | #endif | ||
130 | // Unload | 134 | // Unload |
131 | AppDomain.Unload(ads.CurrentAppDomain); | 135 | AppDomain.Unload(ads.CurrentAppDomain); |
136 | #if DEBUG | ||
137 | Console.WriteLine("AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory"); | ||
138 | #endif | ||
132 | } | 139 | } |
133 | } | 140 | } |
134 | } // foreach | 141 | } // foreach |
@@ -142,20 +149,12 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
142 | // Find next available AppDomain to put it in | 149 | // Find next available AppDomain to put it in |
143 | AppDomainStructure FreeAppDomain = GetFreeAppDomain(); | 150 | AppDomainStructure FreeAppDomain = GetFreeAppDomain(); |
144 | 151 | ||
145 | //if (FreeAppDomain == null) Console.WriteLine("FreeAppDomain == null"); | ||
146 | //if (FreeAppDomain.CurrentAppDomain == null) Console.WriteLine("FreeAppDomain.CurrentAppDomain == null"); | ||
147 | Console.WriteLine("Loading into AppDomain: " + FileName); | 152 | Console.WriteLine("Loading into AppDomain: " + FileName); |
148 | LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); | 153 | LSL_BaseClass mbrt = (LSL_BaseClass)FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); |
149 | //Type mytype = mbrt.GetType(); | 154 | //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); |
150 | Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); | ||
151 | |||
152 | // Increase script count in tihs AppDomain | ||
153 | FreeAppDomain.ScriptsLoaded++; | 155 | FreeAppDomain.ScriptsLoaded++; |
154 | 156 | ||
155 | //mbrt.Start(); | ||
156 | return mbrt; | 157 | return mbrt; |
157 | //return (LSL_BaseClass)mbrt; | ||
158 | |||
159 | } | 158 | } |
160 | 159 | ||
161 | 160 | ||
@@ -168,6 +167,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
168 | { | 167 | { |
169 | lock (FreeLock) | 168 | lock (FreeLock) |
170 | { | 169 | { |
170 | Console.WriteLine("Stopping script in AppDomain"); | ||
171 | // Check if it is current AppDomain | 171 | // Check if it is current AppDomain |
172 | if (CurrentAD.CurrentAppDomain == ad) | 172 | if (CurrentAD.CurrentAppDomain == ad) |
173 | { | 173 | { |
@@ -181,15 +181,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
181 | { | 181 | { |
182 | if (ads.CurrentAppDomain == ad) | 182 | if (ads.CurrentAppDomain == ad) |
183 | { | 183 | { |
184 | // Found it - messy code to increase structure | 184 | // Found it |
185 | //AppDomainStructure ads2 = ads; | ||
186 | ads.ScriptsWaitingUnload++; | 185 | ads.ScriptsWaitingUnload++; |
187 | //AppDomains.Remove(ads); | 186 | break; |
188 | //AppDomains.Add(ads2); | ||
189 | return; | ||
190 | } | 187 | } |
191 | } // foreach | 188 | } // foreach |
192 | } // lock | 189 | } // lock |
190 | |||
191 | UnloadAppDomains(); // Outsite lock, has its own GetLock | ||
192 | |||
193 | |||
193 | } | 194 | } |
194 | 195 | ||
195 | 196 | ||
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs index bfb8913..cb0f9ba 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/LSL/LSL_BaseClass.cs | |||
@@ -5,14 +5,33 @@ using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; | |||
5 | using OpenSim.Region.ScriptEngine.Common; | 5 | using OpenSim.Region.ScriptEngine.Common; |
6 | using System.Threading; | 6 | using System.Threading; |
7 | using System.Reflection; | 7 | using System.Reflection; |
8 | 8 | using System.Runtime.Remoting.Lifetime; | |
9 | 9 | ||
10 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL | 10 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL |
11 | { | 11 | { |
12 | public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript | 12 | public class LSL_BaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, IScript |
13 | { | 13 | { |
14 | |||
15 | // Object never expires | ||
16 | public override Object InitializeLifetimeService() | ||
17 | { | ||
18 | Console.WriteLine("LSL_BaseClass: InitializeLifetimeService()"); | ||
19 | // return null; | ||
20 | ILease lease = (ILease)base.InitializeLifetimeService(); | ||
21 | |||
22 | if (lease.CurrentState == LeaseState.Initial) | ||
23 | { | ||
24 | lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); | ||
25 | //lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); | ||
26 | //lease.RenewOnCallTime = TimeSpan.FromSeconds(2); | ||
27 | } | ||
28 | return lease; | ||
29 | } | ||
30 | |||
31 | |||
14 | private Executor m_Exec; | 32 | private Executor m_Exec; |
15 | public Executor Exec { | 33 | public Executor Exec |
34 | { | ||
16 | get | 35 | get |
17 | { | 36 | { |
18 | if (m_Exec == null) | 37 | if (m_Exec == null) |
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs index ca51542..187ac59 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/Compiler/Server_API/LSL_BuiltIn_Commands.cs | |||
@@ -7,6 +7,7 @@ using OpenSim.Region.Environment.Scenes.Scripting; | |||
7 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; | 7 | using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler; |
8 | using OpenSim.Region.ScriptEngine.Common; | 8 | using OpenSim.Region.ScriptEngine.Common; |
9 | using OpenSim.Framework.Console; | 9 | using OpenSim.Framework.Console; |
10 | using System.Runtime.Remoting.Lifetime; | ||
10 | 11 | ||
11 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | 12 | namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler |
12 | { | 13 | { |
@@ -35,6 +36,23 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine.Compiler | |||
35 | return m_state; | 36 | return m_state; |
36 | } | 37 | } |
37 | 38 | ||
39 | // Object never expires | ||
40 | public override Object InitializeLifetimeService() | ||
41 | { | ||
42 | Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()"); | ||
43 | // return null; | ||
44 | ILease lease = (ILease)base.InitializeLifetimeService(); | ||
45 | |||
46 | if (lease.CurrentState == LeaseState.Initial) | ||
47 | { | ||
48 | lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1); | ||
49 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); | ||
50 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(2); | ||
51 | } | ||
52 | return lease; | ||
53 | } | ||
54 | |||
55 | |||
38 | public Scene World | 56 | public Scene World |
39 | { | 57 | { |
40 | get { return m_manager.World; } | 58 | get { return m_manager.World; } |
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs index ea5500a..986d333 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventManager.cs | |||
@@ -62,7 +62,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
62 | { | 62 | { |
63 | // Add to queue for all scripts in ObjectID object | 63 | // Add to queue for all scripts in ObjectID object |
64 | //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Event: touch_start"); | 64 | //myScriptEngine.m_logger.Verbose("ScriptEngine", "EventManager Event: touch_start"); |
65 | Console.WriteLine("touch_start localID: " + localID); | 65 | //Console.WriteLine("touch_start localID: " + localID); |
66 | myScriptEngine.myEventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] { (int)1 }); | 66 | myScriptEngine.myEventQueueManager.AddToObjectQueue(localID, "touch_start", new object[] { (int)1 }); |
67 | } | 67 | } |
68 | public void OnRezScript(uint localID, LLUUID itemID, string script) | 68 | public void OnRezScript(uint localID, LLUUID itemID, string script) |
@@ -85,6 +85,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
85 | // Path.Combine("ScriptEngines", "Default.lsl"), | 85 | // Path.Combine("ScriptEngines", "Default.lsl"), |
86 | // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() | 86 | // new OpenSim.Region.Environment.Scenes.Scripting.NullScriptHost() |
87 | //); | 87 | //); |
88 | Console.WriteLine("OnRemoveScript localID: " + localID + " LLUID: " + itemID.ToString()); | ||
88 | myScriptEngine.myScriptManager.StopScript( | 89 | myScriptEngine.myScriptManager.StopScript( |
89 | localID, | 90 | localID, |
90 | itemID | 91 | itemID |
@@ -96,7 +97,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
96 | // These needs to be hooked up to OpenSim during init of this class | 97 | // These needs to be hooked up to OpenSim during init of this class |
97 | // then queued in EventQueueManager. | 98 | // then queued in EventQueueManager. |
98 | // When queued in EventQueueManager they need to be LSL compatible (name and params) | 99 | // When queued in EventQueueManager they need to be LSL compatible (name and params) |
99 | public void state_entry() { } | 100 | |
101 | //public void state_entry() { } // | ||
100 | public void state_exit() { } | 102 | public void state_exit() { } |
101 | //public void touch_start() { } | 103 | //public void touch_start() { } |
102 | public void touch() { } | 104 | public void touch() { } |
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs index 012e60d..1cab01e 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/EventQueueManager.cs | |||
@@ -243,7 +243,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
243 | // Do we have any scripts in this object at all? If not, return | 243 | // Do we have any scripts in this object at all? If not, return |
244 | if (myScriptEngine.myScriptManager.Scripts.ContainsKey(localID) == false) | 244 | if (myScriptEngine.myScriptManager.Scripts.ContainsKey(localID) == false) |
245 | { | 245 | { |
246 | Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); | 246 | //Console.WriteLine("Event \"" + FunctionName + "\" for localID: " + localID + ". No scripts found on this localID."); |
247 | return; | 247 | return; |
248 | } | 248 | } |
249 | 249 | ||
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index cadae05..9621e56 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs | |||
@@ -50,11 +50,82 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
50 | public class ScriptManager | 50 | public class ScriptManager |
51 | { | 51 | { |
52 | 52 | ||
53 | private Thread ScriptLoadUnloadThread; | ||
54 | private int ScriptLoadUnloadThread_IdleSleepms = 100; | ||
55 | private Queue<LoadStruct> LoadQueue = new Queue<LoadStruct>(); | ||
56 | private Queue<UnloadStruct> UnloadQueue = new Queue<UnloadStruct>(); | ||
57 | private struct LoadStruct | ||
58 | { | ||
59 | public uint localID; | ||
60 | public LLUUID itemID; | ||
61 | public string Script; | ||
62 | } | ||
63 | private struct UnloadStruct | ||
64 | { | ||
65 | public uint localID; | ||
66 | public LLUUID itemID; | ||
67 | } | ||
68 | |||
53 | private ScriptEngine m_scriptEngine; | 69 | private ScriptEngine m_scriptEngine; |
54 | public ScriptManager(ScriptEngine scriptEngine) | 70 | public ScriptManager(ScriptEngine scriptEngine) |
55 | { | 71 | { |
56 | m_scriptEngine = scriptEngine; | 72 | m_scriptEngine = scriptEngine; |
57 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); | 73 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); |
74 | ScriptLoadUnloadThread = new Thread(ScriptLoadUnloadThreadLoop); | ||
75 | ScriptLoadUnloadThread.Name = "ScriptLoadUnloadThread"; | ||
76 | ScriptLoadUnloadThread.IsBackground = true; | ||
77 | ScriptLoadUnloadThread.Priority = ThreadPriority.BelowNormal; | ||
78 | ScriptLoadUnloadThread.Start(); | ||
79 | |||
80 | } | ||
81 | ~ScriptManager () | ||
82 | { | ||
83 | // Abort load/unload thread | ||
84 | try | ||
85 | { | ||
86 | if (ScriptLoadUnloadThread != null) | ||
87 | { | ||
88 | if (ScriptLoadUnloadThread.IsAlive == true) | ||
89 | { | ||
90 | ScriptLoadUnloadThread.Abort(); | ||
91 | ScriptLoadUnloadThread.Join(); | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | catch | ||
96 | { | ||
97 | } | ||
98 | } | ||
99 | private void ScriptLoadUnloadThreadLoop() | ||
100 | { | ||
101 | try | ||
102 | { | ||
103 | while (true) | ||
104 | { | ||
105 | if (LoadQueue.Count == 0 && UnloadQueue.Count == 0) | ||
106 | Thread.Sleep(ScriptLoadUnloadThread_IdleSleepms); | ||
107 | |||
108 | if (LoadQueue.Count > 0) | ||
109 | { | ||
110 | LoadStruct item = LoadQueue.Dequeue(); | ||
111 | _StartScript(item.localID, item.itemID, item.Script); | ||
112 | } | ||
113 | |||
114 | if (UnloadQueue.Count > 0) | ||
115 | { | ||
116 | UnloadStruct item = UnloadQueue.Dequeue(); | ||
117 | _StopScript(item.localID, item.itemID); | ||
118 | } | ||
119 | |||
120 | |||
121 | |||
122 | } | ||
123 | } | ||
124 | catch (ThreadAbortException tae) | ||
125 | { | ||
126 | // Expected | ||
127 | } | ||
128 | |||
58 | } | 129 | } |
59 | 130 | ||
60 | private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) | 131 | private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) |
@@ -146,8 +217,29 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
146 | /// <param name="localID"></param> | 217 | /// <param name="localID"></param> |
147 | public void StartScript(uint localID, LLUUID itemID, string Script) | 218 | public void StartScript(uint localID, LLUUID itemID, string Script) |
148 | { | 219 | { |
220 | LoadStruct ls = new LoadStruct(); | ||
221 | ls.localID = localID; | ||
222 | ls.itemID = itemID; | ||
223 | ls.Script = Script; | ||
224 | LoadQueue.Enqueue(ls); | ||
225 | } | ||
226 | /// <summary> | ||
227 | /// Disables and unloads a script | ||
228 | /// </summary> | ||
229 | /// <param name="localID"></param> | ||
230 | /// <param name="itemID"></param> | ||
231 | public void StopScript(uint localID, LLUUID itemID) | ||
232 | { | ||
233 | UnloadStruct ls = new UnloadStruct(); | ||
234 | ls.localID = localID; | ||
235 | ls.itemID = itemID; | ||
236 | UnloadQueue.Enqueue(ls); | ||
237 | } | ||
238 | |||
239 | private void _StartScript(uint localID, LLUUID itemID, string Script) | ||
240 | { | ||
149 | //IScriptHost root = host.GetRoot(); | 241 | //IScriptHost root = host.GetRoot(); |
150 | m_scriptEngine.Log.Verbose("ScriptEngine", "ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); | 242 | Console.WriteLine("ScriptManager StartScript: localID: " + localID + ", itemID: " + itemID); |
151 | 243 | ||
152 | // We will initialize and start the script. | 244 | // We will initialize and start the script. |
153 | // It will be up to the script itself to hook up the correct events. | 245 | // It will be up to the script itself to hook up the correct events. |
@@ -161,32 +253,23 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
161 | OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler(); | 253 | OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler LSLCompiler = new OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.Compiler(); |
162 | // Compile (We assume LSL) | 254 | // Compile (We assume LSL) |
163 | FileName = LSLCompiler.CompileFromLSLText(Script); | 255 | FileName = LSLCompiler.CompileFromLSLText(Script); |
164 | m_scriptEngine.Log.Verbose("ScriptEngine", "Compilation of " + FileName + " done"); | 256 | Console.WriteLine("Compilation of " + FileName + " done"); |
165 | // * Insert yield into code | 257 | // * Insert yield into code |
166 | FileName = ProcessYield(FileName); | 258 | FileName = ProcessYield(FileName); |
167 | 259 | ||
168 | 260 | ||
169 | //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSO.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName); | 261 | #if DEBUG |
170 | |||
171 | //OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL.LSL_BaseClass Script = LoadAndInitAssembly(FreeAppDomain, FileName, localID); | ||
172 | |||
173 | long before; | 262 | long before; |
174 | before = GC.GetTotalMemory(false); | 263 | before = GC.GetTotalMemory(false); |
264 | #endif | ||
175 | LSL_BaseClass CompiledScript = m_scriptEngine.myAppDomainManager.LoadScript(FileName); | 265 | LSL_BaseClass CompiledScript = m_scriptEngine.myAppDomainManager.LoadScript(FileName); |
266 | #if DEBUG | ||
176 | Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(false) - before); | 267 | Console.WriteLine("Script " + itemID + " occupies {0} bytes", GC.GetTotalMemory(false) - before); |
177 | //before = GC.GetTotalMemory(false); | 268 | #endif |
178 | |||
179 | 269 | ||
180 | //Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); | 270 | // Add it to our script memstruct |
181 | //Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); | ||
182 | //before = GC.GetTotalMemory(true); | ||
183 | //Script = m_scriptEngine.myAppDomainManager.LoadScript(FileName); | ||
184 | //Console.WriteLine("Script occupies {0} bytes", GC.GetTotalMemory(true) - before); | ||
185 | |||
186 | |||
187 | // Add it to our temporary active script keeper | ||
188 | //Scripts.Add(FullitemID, Script); | ||
189 | SetScript(localID, itemID, CompiledScript); | 271 | SetScript(localID, itemID, CompiledScript); |
272 | |||
190 | // We need to give (untrusted) assembly a private instance of BuiltIns | 273 | // We need to give (untrusted) assembly a private instance of BuiltIns |
191 | // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. | 274 | // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. |
192 | LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, World.GetSceneObjectPart(localID)); | 275 | LSL_BuiltIn_Commands LSLB = new LSL_BuiltIn_Commands(this, World.GetSceneObjectPart(localID)); |
@@ -202,9 +285,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
202 | 285 | ||
203 | 286 | ||
204 | } | 287 | } |
205 | public void StopScript(uint localID, LLUUID itemID) | 288 | |
289 | private void _StopScript(uint localID, LLUUID itemID) | ||
206 | { | 290 | { |
207 | // Stop script | 291 | // Stop script |
292 | Console.WriteLine("Stop script localID: " + localID + " LLUID: " + itemID.ToString()); | ||
208 | 293 | ||
209 | // Get AppDomain | 294 | // Get AppDomain |
210 | AppDomain ad = GetScript(localID, itemID).Exec.GetAppDomain(); | 295 | AppDomain ad = GetScript(localID, itemID).Exec.GetAppDomain(); |
@@ -235,7 +320,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
235 | { | 320 | { |
236 | 321 | ||
237 | // Execute a function in the script | 322 | // Execute a function in the script |
238 | m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); | 323 | //m_scriptEngine.Log.Verbose("ScriptEngine", "Executing Function localID: " + localID + ", itemID: " + itemID + ", FunctionName: " + FunctionName); |
239 | LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(localID, itemID); | 324 | LSL_BaseClass Script = m_scriptEngine.myScriptManager.GetScript(localID, itemID); |
240 | 325 | ||
241 | // Must be done in correct AppDomain, so leaving it up to the script itself | 326 | // Must be done in correct AppDomain, so leaving it up to the script itself |