diff options
author | Justin Clark-Casey (justincc) | 2012-08-22 23:04:17 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-08-22 23:04:17 +0100 |
commit | 1369058280c4cf399d46df1508b80cad99f1247e (patch) | |
tree | e6f267cd79312d745f6506e9872c021b4dcb2ff0 | |
parent | BulletSim: update DLLs and SOs to eliminate terrain update crash which manife... (diff) | |
download | opensim-SC_OLD-1369058280c4cf399d46df1508b80cad99f1247e.zip opensim-SC_OLD-1369058280c4cf399d46df1508b80cad99f1247e.tar.gz opensim-SC_OLD-1369058280c4cf399d46df1508b80cad99f1247e.tar.bz2 opensim-SC_OLD-1369058280c4cf399d46df1508b80cad99f1247e.tar.xz |
Lock disposal of separate gdi+ objects under different threads since this prevents malloc heap corruption seen under Ubuntu 10.04.1 and 11.04 - probably a libcairo issue
In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously,
the native malloc heap can become corrupted, possibly due to a double free(). This may be due to
bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were
seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed
under lock.
-rw-r--r-- | OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index ca320e1..c48a703 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs | |||
@@ -308,36 +308,44 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
308 | 308 | ||
309 | try | 309 | try |
310 | { | 310 | { |
311 | if (alpha == 256) | 311 | // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, |
312 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); | 312 | // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to |
313 | else | 313 | // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were |
314 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); | 314 | // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed |
315 | 315 | // under lock. | |
316 | graph = Graphics.FromImage(bitmap); | 316 | lock (this) |
317 | |||
318 | // this is really just to save people filling the | ||
319 | // background color in their scripts, only do when fully opaque | ||
320 | if (alpha >= 255) | ||
321 | { | 317 | { |
322 | using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) | 318 | if (alpha == 256) |
319 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); | ||
320 | else | ||
321 | bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); | ||
322 | |||
323 | graph = Graphics.FromImage(bitmap); | ||
324 | |||
325 | // this is really just to save people filling the | ||
326 | // background color in their scripts, only do when fully opaque | ||
327 | if (alpha >= 255) | ||
323 | { | 328 | { |
324 | graph.FillRectangle(bgFillBrush, 0, 0, width, height); | 329 | using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) |
330 | { | ||
331 | graph.FillRectangle(bgFillBrush, 0, 0, width, height); | ||
332 | } | ||
325 | } | 333 | } |
326 | } | 334 | |
327 | 335 | for (int w = 0; w < bitmap.Width; w++) | |
328 | for (int w = 0; w < bitmap.Width; w++) | ||
329 | { | ||
330 | if (alpha <= 255) | ||
331 | { | 336 | { |
332 | for (int h = 0; h < bitmap.Height; h++) | 337 | if (alpha <= 255) |
333 | { | 338 | { |
334 | bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); | 339 | for (int h = 0; h < bitmap.Height; h++) |
340 | { | ||
341 | bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); | ||
342 | } | ||
335 | } | 343 | } |
336 | } | 344 | } |
345 | |||
346 | GDIDraw(data, graph, altDataDelim); | ||
337 | } | 347 | } |
338 | 348 | ||
339 | GDIDraw(data, graph, altDataDelim); | ||
340 | |||
341 | byte[] imageJ2000 = new byte[0]; | 349 | byte[] imageJ2000 = new byte[0]; |
342 | 350 | ||
343 | try | 351 | try |
@@ -355,11 +363,19 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender | |||
355 | } | 363 | } |
356 | finally | 364 | finally |
357 | { | 365 | { |
358 | if (graph != null) | 366 | // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, |
359 | graph.Dispose(); | 367 | // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to |
360 | 368 | // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were | |
361 | if (bitmap != null) | 369 | // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed |
362 | bitmap.Dispose(); | 370 | // under lock. |
371 | lock (this) | ||
372 | { | ||
373 | if (graph != null) | ||
374 | graph.Dispose(); | ||
375 | |||
376 | if (bitmap != null) | ||
377 | bitmap.Dispose(); | ||
378 | } | ||
363 | } | 379 | } |
364 | } | 380 | } |
365 | 381 | ||