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 /OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs | |
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.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs | 123 |
1 files changed, 104 insertions, 19 deletions
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 |