From c28b3526fe34903bae0b39709c1c655beff7bdd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20G=2E=20Aragoneses?= Date: Tue, 5 Nov 2013 00:14:33 +0100 Subject: [PATCH 1/2] cairo: fix remaining leaks when finalizer gets called Apply same finalizer leak fix to the rest of IDisposable-ownership cairo classes as the one recently committed for Cairo.Context[1]. [1] https://github.com/mono/gtk-sharp/commit/41eeecbf9a6d84fa29ccee9adfee98ada1f1de66 --- cairo/FontFace.cs | 2 +- cairo/FontOptions.cs | 2 +- cairo/Path.cs | 2 +- cairo/Pattern.cs | 2 +- cairo/Region.cs | 2 +- cairo/ScaledFont.cs | 2 +- cairo/Surface.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cairo/FontFace.cs b/cairo/FontFace.cs index 19d8163c3..514e2f327 100644 --- a/cairo/FontFace.cs +++ b/cairo/FontFace.cs @@ -61,7 +61,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing|| handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_font_face_destroy (handle); diff --git a/cairo/FontOptions.cs b/cairo/FontOptions.cs index 5269d54df..3128928d8 100644 --- a/cairo/FontOptions.cs +++ b/cairo/FontOptions.cs @@ -72,7 +72,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing|| handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_font_options_destroy (handle); diff --git a/cairo/Path.cs b/cairo/Path.cs index f5007feb9..4a84f1d1d 100644 --- a/cairo/Path.cs +++ b/cairo/Path.cs @@ -63,7 +63,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing || handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_path_destroy (handle); diff --git a/cairo/Pattern.cs b/cairo/Pattern.cs index bc0a962a2..396668a3a 100644 --- a/cairo/Pattern.cs +++ b/cairo/Pattern.cs @@ -99,7 +99,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (Handle, disposing); - if (!disposing|| Handle == IntPtr.Zero) + if (Handle == IntPtr.Zero) return; NativeMethods.cairo_pattern_destroy (Handle); diff --git a/cairo/Region.cs b/cairo/Region.cs index cd0ba33fd..1dc15933b 100644 --- a/cairo/Region.cs +++ b/cairo/Region.cs @@ -94,7 +94,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing|| handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_region_destroy (Handle); diff --git a/cairo/ScaledFont.cs b/cairo/ScaledFont.cs index 937194607..d2dcd397b 100644 --- a/cairo/ScaledFont.cs +++ b/cairo/ScaledFont.cs @@ -106,7 +106,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing|| handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_scaled_font_destroy (handle); diff --git a/cairo/Surface.cs b/cairo/Surface.cs index 6fa8c0209..369b4d285 100644 --- a/cairo/Surface.cs +++ b/cairo/Surface.cs @@ -144,7 +144,7 @@ protected virtual void Dispose (bool disposing) if (!disposing || CairoDebug.Enabled) CairoDebug.OnDisposed (handle, disposing); - if (!disposing || handle == IntPtr.Zero) + if (handle == IntPtr.Zero) return; NativeMethods.cairo_surface_destroy (handle); From 5cc02f314ae0ce55bc28125dc8ca750cf9d464c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20G=2E=20Aragoneses?= Date: Tue, 5 Nov 2013 14:09:55 +0100 Subject: [PATCH 2/2] cairo: use a GLib.Timeout for calling destroy (unref) functions Since some finalizer leaks started to get fixed ([1],[2]) hangs, freezes, and X11 crashes were a bit more frequent. Queuing the refcount decrease using a GLib.Timeout fixes them. [1] https://github.com/mono/gtk-sharp/commit/41eeecbf9a6d84fa29ccee9adfee98ada1f1de66 [2] https://github.com/mono/gtk-sharp/commit/c28b3526fe34903bae0b39709c1c655beff7bdd8 --- cairo/Context.cs | 2 +- cairo/Device.cs | 2 +- cairo/FontFace.cs | 2 +- cairo/FontOptions.cs | 2 +- cairo/Global.cs | 44 ++++++++++++++++++++++++++++++++++++++++++ cairo/Makefile.am | 2 ++ cairo/NativeMethods.cs | 2 +- cairo/Path.cs | 2 +- cairo/Pattern.cs | 2 +- cairo/Region.cs | 2 +- cairo/ScaledFont.cs | 2 +- cairo/Surface.cs | 2 +- cairo/cairo.csproj | 7 +++++++ 13 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 cairo/Global.cs diff --git a/cairo/Context.cs b/cairo/Context.cs index 73df43807..6b1b54cd8 100644 --- a/cairo/Context.cs +++ b/cairo/Context.cs @@ -118,7 +118,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/Device.cs b/cairo/Device.cs index 06d31c523..162c68aed 100644 --- a/cairo/Device.cs +++ b/cairo/Device.cs @@ -52,7 +52,7 @@ public Status Acquire () public void Dispose () { if (handle != IntPtr.Zero) - NativeMethods.cairo_device_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_device_destroy, handle); handle = IntPtr.Zero; GC.SuppressFinalize (this); } diff --git a/cairo/FontFace.cs b/cairo/FontFace.cs index 514e2f327..5f4671f4d 100644 --- a/cairo/FontFace.cs +++ b/cairo/FontFace.cs @@ -64,7 +64,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_font_face_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_font_face_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/FontOptions.cs b/cairo/FontOptions.cs index 3128928d8..b0eaf5806 100644 --- a/cairo/FontOptions.cs +++ b/cairo/FontOptions.cs @@ -75,7 +75,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_font_options_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_font_options_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/Global.cs b/cairo/Global.cs new file mode 100644 index 000000000..0d61ba433 --- /dev/null +++ b/cairo/Global.cs @@ -0,0 +1,44 @@ +// +// Mono.Cairo.Global.cs +// +// Authors: +// Andrés G. Aragoneses +// +// (C) Andrés G. Aragoneses, 2013. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Cairo +{ + internal class Global + { + internal static void QueueUnref (Action unref_native_function, IntPtr handle) + { + GLib.Timeout.Add (50, () => { + unref_native_function (handle); + return false; + }); + } + } +} + diff --git a/cairo/Makefile.am b/cairo/Makefile.am index 82eb2314c..1038aa815 100644 --- a/cairo/Makefile.am +++ b/cairo/Makefile.am @@ -1,6 +1,7 @@ ASSEMBLY_NAME = cairo-sharp ASSEMBLY_NAME_VERSION = $(ASSEMBLY_NAME),Version=$(CAIRO_API_VERSION) ASSEMBLY = $(ASSEMBLY_NAME).dll +references = -r:$(top_builddir)/glib/glib-sharp.dll SNK = $(srcdir)/mono.snk TARGET=$(ASSEMBLY) @@ -29,6 +30,7 @@ sources = \ FontType.cs \ FontWeight.cs \ Format.cs \ + Global.cs \ GlitzSurface.cs \ Glyph.cs \ Gradient.cs \ diff --git a/cairo/NativeMethods.cs b/cairo/NativeMethods.cs index 20fa29998..843740e0c 100644 --- a/cairo/NativeMethods.cs +++ b/cairo/NativeMethods.cs @@ -700,7 +700,7 @@ internal static class NativeMethods internal static extern IntPtr cairo_scaled_font_create (IntPtr fontFace, Matrix matrix, Matrix ctm, IntPtr options); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] - internal static extern IntPtr cairo_scaled_font_destroy (IntPtr scaled_font); + internal static extern void cairo_scaled_font_destroy (IntPtr scaled_font); [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] internal static extern void cairo_scaled_font_extents (IntPtr scaled_font, out FontExtents extents); diff --git a/cairo/Path.cs b/cairo/Path.cs index 4a84f1d1d..73cf59d54 100644 --- a/cairo/Path.cs +++ b/cairo/Path.cs @@ -66,7 +66,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_path_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_path_destroy, handle); handle = IntPtr.Zero; } } diff --git a/cairo/Pattern.cs b/cairo/Pattern.cs index 396668a3a..81b0ebc56 100644 --- a/cairo/Pattern.cs +++ b/cairo/Pattern.cs @@ -102,7 +102,7 @@ protected virtual void Dispose (bool disposing) if (Handle == IntPtr.Zero) return; - NativeMethods.cairo_pattern_destroy (Handle); + Global.QueueUnref (NativeMethods.cairo_pattern_destroy, Handle); Handle = IntPtr.Zero; } diff --git a/cairo/Region.cs b/cairo/Region.cs index 1dc15933b..51d90a387 100644 --- a/cairo/Region.cs +++ b/cairo/Region.cs @@ -97,7 +97,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_region_destroy (Handle); + Global.QueueUnref (NativeMethods.cairo_region_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/ScaledFont.cs b/cairo/ScaledFont.cs index d2dcd397b..e183fc119 100644 --- a/cairo/ScaledFont.cs +++ b/cairo/ScaledFont.cs @@ -109,7 +109,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_scaled_font_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_scaled_font_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/Surface.cs b/cairo/Surface.cs index 369b4d285..f00c1f136 100644 --- a/cairo/Surface.cs +++ b/cairo/Surface.cs @@ -147,7 +147,7 @@ protected virtual void Dispose (bool disposing) if (handle == IntPtr.Zero) return; - NativeMethods.cairo_surface_destroy (handle); + Global.QueueUnref (NativeMethods.cairo_surface_destroy, handle); handle = IntPtr.Zero; } diff --git a/cairo/cairo.csproj b/cairo/cairo.csproj index 0d58b7787..da5a2d624 100644 --- a/cairo/cairo.csproj +++ b/cairo/cairo.csproj @@ -88,5 +88,12 @@ + + + + + {3BF1D531-8840-4F15-8066-A9788D8C398B} + glib + \ No newline at end of file