diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs | 106 |
1 files changed, 39 insertions, 67 deletions
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs index 5a77d39..da461e3 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/AppDomainManager.cs | |||
@@ -37,46 +37,37 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
37 | public class AppDomainManager : iScriptEngineFunctionModule | 37 | public class AppDomainManager : iScriptEngineFunctionModule |
38 | { | 38 | { |
39 | // | 39 | // |
40 | // This class does AppDomain handling and loading/unloading of scripts in it. | 40 | // This class does AppDomain handling and loading/unloading of |
41 | // It is instanced in "ScriptEngine" and controlled from "ScriptManager" | 41 | // scripts in it. It is instanced in "ScriptEngine" and controlled |
42 | // from "ScriptManager" | ||
42 | // | 43 | // |
43 | // 1. Create a new AppDomain if old one is full (or doesn't exist) | 44 | // 1. Create a new AppDomain if old one is full (or doesn't exist) |
44 | // 2. Load scripts into AppDomain | 45 | // 2. Load scripts into AppDomain |
45 | // 3. Unload scripts from AppDomain (stopping them and marking them as inactive) | 46 | // 3. Unload scripts from AppDomain (stopping them and marking |
47 | // them as inactive) | ||
46 | // 4. Unload AppDomain completely when all scripts in it has stopped | 48 | // 4. Unload AppDomain completely when all scripts in it has stopped |
47 | // | 49 | // |
48 | 50 | ||
49 | private int maxScriptsPerAppDomain = 1; | 51 | private int maxScriptsPerAppDomain = 1; |
50 | 52 | ||
51 | /// <summary> | 53 | // Internal list of all AppDomains |
52 | /// Internal list of all AppDomains | 54 | private List<AppDomainStructure> appDomains = |
53 | /// </summary> | 55 | new List<AppDomainStructure>(); |
54 | private List<AppDomainStructure> appDomains = new List<AppDomainStructure>(); | ||
55 | 56 | ||
56 | /// <summary> | 57 | // Structure to keep track of data around AppDomain |
57 | /// Structure to keep track of data around AppDomain | ||
58 | /// </summary> | ||
59 | private class AppDomainStructure | 58 | private class AppDomainStructure |
60 | { | 59 | { |
61 | /// <summary> | 60 | // The AppDomain itself |
62 | /// The AppDomain itself | ||
63 | /// </summary> | ||
64 | public AppDomain CurrentAppDomain; | 61 | public AppDomain CurrentAppDomain; |
65 | 62 | ||
66 | /// <summary> | 63 | // Number of scripts loaded into AppDomain |
67 | /// Number of scripts loaded into AppDomain | ||
68 | /// </summary> | ||
69 | public int ScriptsLoaded; | 64 | public int ScriptsLoaded; |
70 | 65 | ||
71 | /// <summary> | 66 | // Number of dead scripts |
72 | /// Number of dead scripts | ||
73 | /// </summary> | ||
74 | public int ScriptsWaitingUnload; | 67 | public int ScriptsWaitingUnload; |
75 | } | 68 | } |
76 | 69 | ||
77 | /// <summary> | 70 | // Current AppDomain |
78 | /// Current AppDomain | ||
79 | /// </summary> | ||
80 | private AppDomainStructure currentAD; | 71 | private AppDomainStructure currentAD; |
81 | 72 | ||
82 | private object getLock = new object(); // Mutex | 73 | private object getLock = new object(); // Mutex |
@@ -92,20 +83,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
92 | 83 | ||
93 | public void ReadConfig() | 84 | public void ReadConfig() |
94 | { | 85 | { |
95 | maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt("ScriptsPerAppDomain", 1); | 86 | maxScriptsPerAppDomain = m_scriptEngine.ScriptConfigSource.GetInt( |
87 | "ScriptsPerAppDomain", 1); | ||
96 | } | 88 | } |
97 | 89 | ||
98 | /// <summary> | 90 | // Find a free AppDomain, creating one if necessary |
99 | /// Find a free AppDomain, creating one if necessary | ||
100 | /// </summary> | ||
101 | /// <returns>Free AppDomain</returns> | ||
102 | private AppDomainStructure GetFreeAppDomain() | 91 | private AppDomainStructure GetFreeAppDomain() |
103 | { | 92 | { |
104 | // Console.WriteLine("Finding free AppDomain"); | ||
105 | lock (getLock) | 93 | lock (getLock) |
106 | { | 94 | { |
107 | // Current full? | 95 | // Current full? |
108 | if (currentAD != null && currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) | 96 | if (currentAD != null && |
97 | currentAD.ScriptsLoaded >= maxScriptsPerAppDomain) | ||
109 | { | 98 | { |
110 | // Add it to AppDomains list and empty current | 99 | // Add it to AppDomains list and empty current |
111 | appDomains.Add(currentAD); | 100 | appDomains.Add(currentAD); |
@@ -119,21 +108,18 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
119 | currentAD.CurrentAppDomain = PrepareNewAppDomain(); | 108 | currentAD.CurrentAppDomain = PrepareNewAppDomain(); |
120 | } | 109 | } |
121 | 110 | ||
122 | // Console.WriteLine("Scripts loaded in this Appdomain: " + currentAD.ScriptsLoaded); | ||
123 | return currentAD; | 111 | return currentAD; |
124 | } | 112 | } |
125 | } | 113 | } |
126 | 114 | ||
127 | private int AppDomainNameCount; | 115 | private int AppDomainNameCount; |
128 | 116 | ||
129 | /// <summary> | 117 | // Create and prepare a new AppDomain for scripts |
130 | /// Create and prepare a new AppDomain for scripts | ||
131 | /// </summary> | ||
132 | /// <returns>The new AppDomain</returns> | ||
133 | private AppDomain PrepareNewAppDomain() | 118 | private AppDomain PrepareNewAppDomain() |
134 | { | 119 | { |
135 | // Create and prepare a new AppDomain | 120 | // Create and prepare a new AppDomain |
136 | AppDomainNameCount++; | 121 | AppDomainNameCount++; |
122 | |||
137 | // TODO: Currently security match current appdomain | 123 | // TODO: Currently security match current appdomain |
138 | 124 | ||
139 | // Construct and initialize settings for a second AppDomain. | 125 | // Construct and initialize settings for a second AppDomain. |
@@ -143,21 +129,24 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
143 | ads.DisallowCodeDownload = true; | 129 | ads.DisallowCodeDownload = true; |
144 | ads.LoaderOptimization = LoaderOptimization.MultiDomainHost; | 130 | ads.LoaderOptimization = LoaderOptimization.MultiDomainHost; |
145 | ads.ShadowCopyFiles = "false"; // Disable shadowing | 131 | ads.ShadowCopyFiles = "false"; // Disable shadowing |
146 | ads.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; | 132 | ads.ConfigurationFile = |
133 | AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; | ||
147 | 134 | ||
148 | 135 | ||
149 | AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + AppDomainNameCount, null, ads); | 136 | AppDomain AD = AppDomain.CreateDomain("ScriptAppDomain_" + |
150 | m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain Loading: " + | 137 | AppDomainNameCount, null, ads); |
151 | AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll").ToString()); | 138 | m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + |
152 | AD.Load(AssemblyName.GetAssemblyName("OpenSim.Region.ScriptEngine.Shared.dll")); | 139 | "]: AppDomain Loading: " + |
140 | AssemblyName.GetAssemblyName( | ||
141 | "OpenSim.Region.ScriptEngine.Shared.dll").ToString()); | ||
142 | AD.Load(AssemblyName.GetAssemblyName( | ||
143 | "OpenSim.Region.ScriptEngine.Shared.dll")); | ||
153 | 144 | ||
154 | // Return the new AppDomain | 145 | // Return the new AppDomain |
155 | return AD; | 146 | return AD; |
156 | } | 147 | } |
157 | 148 | ||
158 | /// <summary> | 149 | // Unload appdomains that are full and have only dead scripts |
159 | /// Unload appdomains that are full and have only dead scripts | ||
160 | /// </summary> | ||
161 | private void UnloadAppDomains() | 150 | private void UnloadAppDomains() |
162 | { | 151 | { |
163 | lock (freeLock) | 152 | lock (freeLock) |
@@ -174,15 +163,9 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
174 | { | 163 | { |
175 | // Remove from internal list | 164 | // Remove from internal list |
176 | appDomains.Remove(ads); | 165 | appDomains.Remove(ads); |
177 | //#if DEBUG | 166 | |
178 | //Console.WriteLine("Found empty AppDomain, unloading"); | ||
179 | //long m = GC.GetTotalMemory(true); // This force a garbage collect that freezes some windows plateforms | ||
180 | //#endif | ||
181 | // Unload | 167 | // Unload |
182 | AppDomain.Unload(ads.CurrentAppDomain); | 168 | AppDomain.Unload(ads.CurrentAppDomain); |
183 | //#if DEBUG | ||
184 | //m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: AppDomain unload freed " + (m - GC.GetTotalMemory(true)) + " bytes of memory"); | ||
185 | //#endif | ||
186 | } | 169 | } |
187 | } | 170 | } |
188 | } | 171 | } |
@@ -194,13 +177,10 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
194 | // Find next available AppDomain to put it in | 177 | // Find next available AppDomain to put it in |
195 | AppDomainStructure FreeAppDomain = GetFreeAppDomain(); | 178 | AppDomainStructure FreeAppDomain = GetFreeAppDomain(); |
196 | 179 | ||
197 | #if DEBUG | 180 | IScript mbrt = (IScript) |
198 | m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Loading into AppDomain: " + FileName); | 181 | FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap( |
199 | #endif | 182 | FileName, "SecondLife.Script"); |
200 | IScript mbrt = | 183 | |
201 | (IScript) | ||
202 | FreeAppDomain.CurrentAppDomain.CreateInstanceFromAndUnwrap(FileName, "SecondLife.Script"); | ||
203 | //Console.WriteLine("ScriptEngine AppDomainManager: is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); | ||
204 | FreeAppDomain.ScriptsLoaded++; | 184 | FreeAppDomain.ScriptsLoaded++; |
205 | ad = FreeAppDomain.CurrentAppDomain; | 185 | ad = FreeAppDomain.CurrentAppDomain; |
206 | 186 | ||
@@ -208,18 +188,11 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
208 | } | 188 | } |
209 | 189 | ||
210 | 190 | ||
211 | /// <summary> | 191 | // Increase "dead script" counter for an AppDomain |
212 | /// Increase "dead script" counter for an AppDomain | ||
213 | /// </summary> | ||
214 | /// <param name="ad"></param> | ||
215 | //[Obsolete("Needs fixing, needs a real purpose in life!!!")] | ||
216 | public void StopScript(AppDomain ad) | 192 | public void StopScript(AppDomain ad) |
217 | { | 193 | { |
218 | lock (freeLock) | 194 | lock (freeLock) |
219 | { | 195 | { |
220 | #if DEBUG | ||
221 | m_scriptEngine.Log.Info("[" + m_scriptEngine.ScriptEngineName + "]: Stopping script in AppDomain"); | ||
222 | #endif | ||
223 | // Check if it is current AppDomain | 196 | // Check if it is current AppDomain |
224 | if (currentAD.CurrentAppDomain == ad) | 197 | if (currentAD.CurrentAppDomain == ad) |
225 | { | 198 | { |
@@ -243,9 +216,8 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
243 | UnloadAppDomains(); // Outsite lock, has its own GetLock | 216 | UnloadAppDomains(); // Outsite lock, has its own GetLock |
244 | } | 217 | } |
245 | 218 | ||
246 | /// <summary> | 219 | // If set to true then threads and stuff should try |
247 | /// If set to true then threads and stuff should try to make a graceful exit | 220 | // to make a graceful exit |
248 | /// </summary> | ||
249 | public bool PleaseShutdown | 221 | public bool PleaseShutdown |
250 | { | 222 | { |
251 | get { return _PleaseShutdown; } | 223 | get { return _PleaseShutdown; } |