[Mono-dev] SIGSEGV in Cairo.CairoAPI:cairo_get/set_matrix()

John Luke john.luke at gmail.com
Mon Oct 31 16:26:56 EST 2005


Hey,
I think ref is used in too many places.  Perhaps I am wrong, but at 
least for the set_* methods they won't be modifying it.
Maybe going through the cairo docs can help you decide to use 
out/ref/neither for each of those calls, if you didn't already.
For example, cairo_get_matrix looks like it should be out, and 
cairo_set_matrix looks like it should not be ref or out.

For the Matrix struct, the public fields should have the first letter 
capitalized.

The rest looks sane, but I haven't tested it.  Do any of the samples use 
these parts? and if so do they work with these changes?
Hope that helps.

Idan Gazit wrote:
> Ok, so attached is a patch covering the items I mention below.
>
> I expect somebody more experienced with Mono.Cairo should look this
> over, I expect I'll have to make some changes. *nudging Hisham/JLuke*...
>
> Regarding the broken ref arguments, I filed:
>
> http://bugzilla.ximian.com/show_bug.cgi?id=76603
>
> in this regards.
>
> Should I break this patch up into two pieces, one to fix the ref issue
> and one for everything else?
>
> -Idan
>
>
> Idan Gazit wrote:
>   
>> OK, So this email touches on Mono.Cairo in 3 parts:
>>
>> 1. SIGSEGV
>> ==========
>>
>> OK, I got some help from Michael Dominic, who pointed out that
>>
>> cairo_get_matrix (IntPtr cr, Matrix_T matrix);
>>
>> should really be:
>>
>> cairo_get_matrix (IntPtr cr, ref Matrix_T matrix);
>>
>> It seems that any CairoAPI function which takes a matrix should pass a
>> ref Matrix_T and not a Matrix_T. This seems to include the following:
>>
>> cairo_transform
>> cairo_get/set_matrix
>> cairo_set_font_matrix
>> cairo_pattern_get/set_matrix
>>
>> I'm preparing a patch to this effect.
>>
>>
>> 2. Class Or Struct?
>> ===================
>>
>> About this time, lewing (in #mono) suggested that there's no point for
>> Matrix to be a class hiding a Matrix_T struct, rather make Matrix a
>> struct. So I went ahead and did this, and I'm testing it now (looks OK).
>>
>> I don't know the reasons behind wrapping Matrix_T in a class, so can
>> somebody tell me (not sarcastic) why? If there are advantages to having
>> Matrix be a struct and doing away with Matrix_T then I have the patch
>> ready to go.
>>
>> 3. Miscellaneous Design Improvements(?)
>> =======================================
>>
>> Either way to go (struct or class), I saw a few places where changes
>> seemed logical to me:
>>
>> - "Identify" should be "Identity"
>> - Have Translate/Rotate/Scale et al return (this); so as to enable
>> things like myMatrix.Translate().Rotate().Scale().
>> - public static Matrix Identity property as an easy way of getting at
>> the identity matrix.
>> - No need for Pointer nor Raw properties in Matrix (they're not used
>> elsewhere...)?
>> - override Matrix.ToString () to produce something useful for debugging.
>>
>>
>> At any rate, all of these together constitutes a patch to Cairo.cs,
>> Graphics.cs, Matrix.cs, and Pattern.cs. I can make patches for each of
>> the three individually, or whatever.
>>
>> Please let me know how to proceed, I'd be very happy to put in my first
>> patch for mono. :)
>>
>> -Idan
>>
>>
>> Idan Gazit wrote:
>>
>>     
>>> Hey,
>>>
>>> So I manage to segfault when playing with the Graphics.Matrix
>>> property. Basically anything that would result in a call to
>>> cairo_get_matrix or cairo_set_matrix segfaults.
>>>
>>> The stacktrace for this segfault when doing get is below, but
>>> triggering it is pretty easy:
>>>
>>> // set up graphics here, then
>>> System.Console.WriteLine(g.Matrix.ToString());
>>>
>>> the same for set:
>>>
>>> Cairo.Matrix transformMatrix = new Cairo.Matrix ();
>>> transformMatrix.CreateIdentify ();
>>> // set up graphics here, then
>>> g.Matrix = transformMatrix;
>>>
>>>
>>> Should I be talking to the cairo devs aobut this, instead?
>>>
>>> -Idan
>>>
>>> =================================================================
>>> Got a SIGSEGV while executing native code. This usually indicates
>>> a fatal error in the mono runtime or one of the native libraries
>>> used by your application.
>>> =================================================================
>>>
>>> Stacktrace:
>>>
>>>
>>> Native stacktrace:
>>>
>>> in <0x4> (wrapper managed-to-native) Cairo.CairoAPI:cairo_get_matrix
>>> (intptr,Cairo.Matrix_T)
>>> in <0xffffffa1> (wrapper managed-to-native)
>>> Cairo.CairoAPI:cairo_get_matrix (intptr,Cairo.Matrix_T)
>>> in <0x49> Cairo.Graphics:get_Matrix ()
>>> in [0xc1] Meshwork.NetworkMap.ZoomableCairoArea:OnExposeEvent
>>> (Gdk.EventExpose)
>>> in [0x14] Gtk.Widget:exposeevent_cb (intptr,intptr)
>>> in <0x49cce3> (wrapper native-to-managed) Gtk.Widget:exposeevent_cb
>>> (intptr,intptr)
>>> in <0x4> (wrapper managed-to-native) Gtk.Application:gtk_main ()
>>> in <0xffffffe7> (wrapper managed-to-native) Gtk.Application:gtk_main ()
>>> in [0x0] Gtk.Application:Run ()
>>> in [0xb] MainClass:Main (string[])
>>> in <0x50bbe2f9> (wrapper runtime-invoke)
>>> System.Object:runtime_invoke_void_string[] (object,intptr,intptr,intptr)
>>>     mono(mono_handle_native_sigsegv+0x73) [0x813d883]
>>>     mono [0x81108db]
>>>     [0xffffe440]
>>>     /usr/lib/libcairo.so.2(cairo_get_matrix+0x1b) [0xb69343fb]
>>>     [0xb67d4064]
>>>     [0xb67d3fc2]
>>>     [0xb67d0145]
>>>     [0xb67cf725]
>>>     [0xb67cf37e]
>>>     /usr/lib/libgtk-x11-2.0.so.0(_gtk_marshal_BOOLEAN__BOXED+0x58)
>>> [0xb6c6c02c]
>>>     /usr/lib/libgobject-2.0.so.0(g_closure_invoke+0x11e) [0xb697b3a8]
>>>     /usr/lib/libgobject-2.0.so.0 [0xb6989c9f]
>>>     /usr/lib/libgobject-2.0.so.0(g_signal_emit_valist+0x41e) [0xb698aec3]
>>>     /usr/lib/libgobject-2.0.so.0(g_signal_emit+0x29) [0xb698b4c3]
>>>     /usr/lib/libgtk-x11-2.0.so.0 [0xb6d4e16f]
>>>     /usr/lib/libgtk-x11-2.0.so.0(gtk_main_do_event+0x4f7) [0xb6c6ad72]
>>>     /usr/lib/libgdk-x11-2.0.so.0 [0xb6ae6bfa]
>>>     /usr/lib/libgdk-x11-2.0.so.0(gdk_window_process_all_updates+0x95)
>>> [0xb6ae6ccd]
>>>     /usr/lib/libgdk-x11-2.0.so.0 [0xb6ae6d4e]
>>>     /usr/lib/libglib-2.0.so.0 [0xb7f0d750]
>>>     /usr/lib/libglib-2.0.so.0(g_main_context_dispatch+0x1dc) [0xb7f0b4ee]
>>>     /usr/lib/libglib-2.0.so.0 [0xb7f0e4f6]
>>>     /usr/lib/libglib-2.0.so.0(g_main_loop_run+0x1a1) [0xb7f0e7e3]
>>>     /usr/lib/libgtk-x11-2.0.so.0(gtk_main+0xb4) [0xb6c69e65]
>>>     [0xb67cf6a1]
>>>     [0xb67cf660]
>>>     [0xb74d2f12]
>>>     [0xb74d2813]
>>>     mono(mono_runtime_exec_main+0x52) [0x8090ae2]
>>>     mono(mono_runtime_run_main+0x12f) [0x80934ef]
>>>     mono(mono_main+0xeff) [0x805d26f]
>>>     /lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xd2) [0xb7d7bea2]
>>>     mono [0x805be11]
>>> _______________________________________________
>>> Mono-devel-list mailing list
>>> Mono-devel-list at lists.ximian.com
>>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>>>       
>> _______________________________________________
>> Mono-devel-list mailing list
>> Mono-devel-list at lists.ximian.com
>> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>>     
>
>   
> ------------------------------------------------------------------------
>
> Index: Cairo.cs
> ===================================================================
> --- Cairo.cs	(revision 52380)
> +++ Cairo.cs	(working copy)
> @@ -110,12 +110,13 @@
>  
>                  [DllImport (CairoImp)]                
>                  public static extern void cairo_rotate (IntPtr cr, double angle);
> -
> +		
> +		// TODO out keyword necessary?
>                  [DllImport (CairoImp)]
> -                public static extern void cairo_transform (IntPtr cr, out Matrix_T matrix);
> +                public static extern void cairo_transform (IntPtr cr, out Matrix matrix);
>                  
>                  [DllImport (CairoImp)]
> -                public static extern void cairo_set_matrix (IntPtr cr, Matrix_T matrix);
> +                public static extern void cairo_set_matrix (IntPtr cr, ref Matrix matrix);
>                  
>                  [DllImport (CairoImp)]
>                  public static extern void cairo_identity_matrix (IntPtr cr);
> @@ -223,7 +224,7 @@
>  		
>  		[DllImport (CairoImp)]
>                  public static extern void cairo_set_font_matrix (IntPtr cr,
> -							     Matrix_T matrix);
> +							    ref Matrix matrix);
>  		
>                  [DllImport (CairoImp)]
>                  public static extern void cairo_show_text (IntPtr cr, string utf8);
> @@ -305,7 +306,7 @@
>  		public static extern double cairo_get_miter_limit (IntPtr cr);
>  
>                  [DllImport (CairoImp)]
> -                public static extern void cairo_get_matrix (IntPtr cr, Matrix_T matrix);
> +                public static extern void cairo_get_matrix (IntPtr cr, ref Matrix matrix);
>  
>                  [DllImport (CairoImp)]
>                  public static extern IntPtr cairo_get_target (IntPtr cr);
> @@ -382,52 +383,52 @@
>                  //
>  
>                  [DllImport (CairoImp)]                
> -                public static extern void cairo_matrix_init (ref Matrix_T matrix,
> +                public static extern void cairo_matrix_init (ref Matrix matrix,
>  		 double xx, double yx, double xy, double yy, double x0, double y0);
>  		
>  		[DllImport (CairoImp)]                
> -                public static extern void cairo_matrix_init_translate (ref Matrix_T matrix,
> +                public static extern void cairo_matrix_init_translate (ref Matrix matrix,
>  							 double tx, double ty);
>  		
>  		[DllImport (CairoImp)]                
> -                public static extern void cairo_matrix_translate (ref Matrix_T matrix,
> +                public static extern void cairo_matrix_translate (ref Matrix matrix,
>  							 double tx, double ty);
>  		
>                  [DllImport (CairoImp)]
> -                public static extern void cairo_matrix_init_identity (ref Matrix_T matrix);
> +                public static extern void cairo_matrix_init_identity (ref Matrix matrix);
>  
>                  [DllImport (CairoImp)]                
> -                public static extern void cairo_matrix_init_scale (ref Matrix_T matrix,
> +                public static extern void cairo_matrix_init_scale (ref Matrix matrix,
>  								   double sx, 
>  								   double sy);
>  		
>                  [DllImport (CairoImp)]                
> -                public static extern void cairo_matrix_scale (ref Matrix_T matrix,
> +                public static extern void cairo_matrix_scale (ref Matrix matrix,
>  								   double sx, 
>  								   double sy);
>  
>                  [DllImport (CairoImp)]
>                  public static extern void cairo_matrix_init_rotate (
> -                        ref Matrix_T matrix, double radians);		
> +                        ref Matrix matrix, double radians);		
>  		
>                  [DllImport (CairoImp)]                                
>                  public static extern void cairo_matrix_rotate (
> -                        ref Matrix_T matrix, double radians);
> +                        ref Matrix matrix, double radians);
>  
>                  [DllImport (CairoImp)]                                
> -                public static extern Cairo.Status cairo_matrix_invert (ref Matrix_T matrix);
> +                public static extern Cairo.Status cairo_matrix_invert (ref Matrix matrix);
>  
>                  [DllImport (CairoImp)]                                
>                  public static extern void cairo_matrix_multiply (
> -                        ref Matrix_T result, ref Matrix_T a, ref Matrix_T b);
> +                        ref Matrix result, ref Matrix a, ref Matrix b);
>  
>                  [DllImport (CairoImp)]                                
>                  public static extern void cairo_matrix_transform_distance (
> -                        ref Matrix_T matrix, ref double dx, ref double dy);
> +                        ref Matrix matrix, ref double dx, ref double dy);
>  
>                  [DllImport (CairoImp)]                                
>                  public static extern void cairo_matrix_transform_point (
> -                        ref Matrix_T matrix, ref double x, ref double y);
> +                        ref Matrix matrix, ref double x, ref double y);
>  
>                  //
>                  // Pattern functions
> @@ -469,10 +470,10 @@
>  		        double offset, double red, double green, double blue);
>  
>                  [DllImport (CairoImp)]
> -                public static extern Status cairo_pattern_set_matrix (IntPtr pattern, IntPtr matrix);
> +                public static extern Status cairo_pattern_set_matrix (IntPtr pattern, ref Matrix matrix);
>  
>                  [DllImport (CairoImp)]
> -                public static extern Status cairo_pattern_get_matrix (IntPtr pattern, IntPtr matrix);
> +                public static extern Status cairo_pattern_get_matrix (IntPtr pattern, ref Matrix matrix);
>  
>                  [DllImport (CairoImp)]
>                  public static extern Status cairo_pattern_set_extend (IntPtr pattern, Extend extend);
> Index: Pattern.cs
> ===================================================================
> --- Pattern.cs	(revision 52380)
> +++ Pattern.cs	(working copy)
> @@ -132,17 +132,13 @@
>                  public Matrix Matrix {
>                          set { 
>  				CairoAPI.cairo_pattern_set_matrix (pattern,
> -								   value.Raw);
> +								   ref value);
>  			}
>  
>                          get {
> -				Matrix_T matrix = new Matrix_T ();				
> -				IntPtr p = Marshal.AllocCoTaskMem ( Marshal.SizeOf (matrix));
> -				Marshal.StructureToPtr (matrix, p, true);
> -				CairoAPI.cairo_pattern_get_matrix (pattern, p);
> -				matrix = (Matrix_T)Marshal.PtrToStructure(p, typeof(Matrix_T));
> -				Marshal.FreeCoTaskMem (p);
> -				return new Cairo.Matrix (matrix);
> +				Matrix m = new Matrix ();
> +				CairoAPI.cairo_pattern_get_matrix (pattern, ref m);
> +				return m;
>                          }
>                  }
>  
> Index: Graphics.cs
> ===================================================================
> --- Graphics.cs	(revision 52380)
> +++ Graphics.cs	(working copy)
> @@ -527,13 +527,13 @@
>  		
>                  public Cairo.Matrix Matrix {
>                          set {
> -                                CairoAPI.cairo_set_matrix (state, value.Pointer);
> +                                CairoAPI.cairo_set_matrix (state, ref value);
>                          }
>  
>                          get {
> -				Matrix_T m = new Matrix_T ();
> -				CairoAPI.cairo_get_matrix (state, m);
> -                                return new Matrix (m);
> +				Matrix m = new Matrix ();
> +				CairoAPI.cairo_get_matrix (state, ref m);
> +                                return m;
>                          }
>                  }
>  		/*
> @@ -560,7 +560,7 @@
>  		
>  		public void FontSetMatrix (Matrix m)
>  		{
> -			CairoAPI.cairo_set_font_matrix (state, m.Pointer);
> +			CairoAPI.cairo_set_font_matrix (state, ref m);
>  		}
>                  
>  		/*
> Index: Matrix.cs
> ===================================================================
> --- Matrix.cs	(revision 52380)
> +++ Matrix.cs	(working copy)
> @@ -33,118 +33,108 @@
>  using System.Runtime.InteropServices;
>  
>  namespace Cairo {
> -   
> -                  
> -   [StructLayout(LayoutKind.Sequential)]
> -   internal struct Matrix_T
> -   {
> -	   public double xx; 
> -	   public double yx;
> -	   public double xy; 
> -	   public double yy;
> -	   public double x0; 
> -	   public double y0;	   
> -   }
> -   
> -   
> -   
> -        public class Matrix
> +
> +   	[StructLayout(LayoutKind.Sequential)]
> +        public struct Matrix
>          {		
> -		internal Matrix_T matrix;
> -		
> -                public Matrix ()       
> +		public double xx;
> +		public double yx;
> +		public double xy; 
> +		public double yy;
> +		public double x0; 
> +		public double y0;	
> +
> +
> +                public Matrix (double xx, double yx, double xy, double yy,
> +				  double x0, double y0)
>                  {               
> -			//CreateIdentify();
> +			this.xx = xx; this.yx = yx; this.xy = xy;
> +			this.yy = yy; this.x0 = x0; this.y0 = y0;
>                  }
> -		
> -                internal Matrix (Matrix_T ptr)
> -                {
> -                        //if (ptr == null)
> -			//  CreateIdentify ();
> -			
> -                        matrix = ptr;
> -                }
> -		
> -                public void CreateIdentify ()
> +
> +		public static Matrix Identity {
> +			get {
> +				Matrix identity = new Matrix ();
> +				identity.InitIdentity();
> +				return identity;
> +			}
> +		}
> +				
> +                public void InitIdentity ()
>                  {			
> -			CairoAPI.cairo_matrix_init_identity (ref matrix);
> +			CairoAPI.cairo_matrix_init_identity (ref this);
>                  }
>  		
> -		public void Init (double xx, double yx, double xy, double yy,
> +		public Matrix Init (double xx, double yx, double xy, double yy,
>  				  double x0, double y0)
>  		{
> -			matrix.xx = xx; matrix.yx = yx; matrix.xy = xy;
> -			matrix.yy = yy; matrix.x0 = x0; matrix.y0 = y0;
> +			this.xx = xx; this.yx = yx; this.xy = xy;
> +			this.yy = yy; this.x0 = x0; this.y0 = y0;
> +			return this;
>  		}
>  		
> -		public void InitTranslate (double tx, double ty)
> +		public Matrix InitTranslate (double tx, double ty)
>  		{		
> -			CairoAPI.cairo_matrix_init_translate (ref matrix, tx, ty);
> +			CairoAPI.cairo_matrix_init_translate (ref this, tx, ty);
> +			return this;
>  		}		
>  		  			       
> -		public void Translate (double tx, double ty)
> +		public Matrix Translate (double tx, double ty)
>  		{
> -			CairoAPI.cairo_matrix_translate (ref matrix, tx, ty);
> +			CairoAPI.cairo_matrix_translate (ref this, tx, ty);
> +			return this;
>  		}
>  		
> -                public void InitScale (double sx, double sy)
> +                public Matrix InitScale (double sx, double sy)
>                  {
> -			CairoAPI.cairo_matrix_init_scale (ref matrix, sx, sy);
> +			CairoAPI.cairo_matrix_init_scale (ref this, sx, sy);
> +			return this;
>                  }		
>  		
> -                public void Scale (double sx, double sy)
> +                public Matrix Scale (double sx, double sy)
>                  {
> -			CairoAPI.cairo_matrix_scale (ref matrix, sx, sy);
> +			CairoAPI.cairo_matrix_scale (ref this, sx, sy);
> +			return this;
>                  }
>  
> -                public void InitRotate (double radians)
> +                public Matrix InitRotate (double radians)
>                  {
> -			CairoAPI.cairo_matrix_init_rotate (ref matrix, radians);
> +			CairoAPI.cairo_matrix_init_rotate (ref this, radians);
> +			return this;
>                  }		
>  		
> -                public void Rotate (double radians)
> +                public Matrix Rotate (double radians)
>                  {
> -			CairoAPI.cairo_matrix_rotate (ref matrix, radians);
> +			CairoAPI.cairo_matrix_rotate (ref this, radians);
> +			return this;
>                  }
>  
>                  public Cairo.Status Invert ()
>                  {
> -			return  CairoAPI.cairo_matrix_invert (ref matrix);
> +			return CairoAPI.cairo_matrix_invert (ref this);
>                  }
>  
> -
> -                public static void Multiply (ref Cairo.Matrix res, 
> -					 ref Cairo.Matrix a, ref Cairo.Matrix b)
> -                {	
> -			if (res == null)
> -			  res = new Matrix ();
> -						
> -                        CairoAPI.cairo_matrix_multiply (ref res.matrix, 
> -							ref a.matrix, 
> -							ref b.matrix);
> -                }
> +		public Matrix Multiply (ref Cairo.Matrix b) {
> +			Matrix result = new Matrix ();
> +			CairoAPI.cairo_matrix_multiply (ref result, ref this, ref b);
> +			return (result);
> +		}
>  		
>                  public void TransformDistance (ref double dx, ref double dy)
>                  {
> -                        CairoAPI.cairo_matrix_transform_distance (ref matrix, ref dx, ref dy);
> +                        CairoAPI.cairo_matrix_transform_distance (ref this, ref dx, ref dy);
>                  }
>  
>                  public void TransformPoint (ref double x, ref double y)
>                  {
> -                        CairoAPI.cairo_matrix_transform_point (ref matrix, ref x, ref y);
> +                        CairoAPI.cairo_matrix_transform_point (ref this, ref x, ref y);
>  		}
> -		
> -                internal Matrix_T Pointer {
> -                        get { return matrix; }
> -			set { matrix = value; }
> -                }
> -		
> -		public IntPtr Raw {
> -			get {
> -				IntPtr p = Marshal.AllocCoTaskMem ( Marshal.SizeOf (matrix));
> -				Marshal.StructureToPtr (matrix, p, true);
> -				return p;
> -			}
> +
> +		public override String ToString ()
> +		{
> +			String s = String.Format ("xx:{0:##0.0#} xy:{1:##0.0#} yy:{2:##0.0#} yx:{3:##0.0#} x0:{4:##0.0#} y0:{5:##0.0#}",
> +				this.xx, this.xy, this.yy, this.yx, this.x0, this.y0);
> +			return s;
>  		}
>  				
>          }
>   
> ------------------------------------------------------------------------
>
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list at lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
>   




More information about the Mono-devel-list mailing list