[Mono-devel-list] marshal.c assertion failed.

Scott Mohekey scott.mohekey at telogis.com
Wed Feb 23 21:02:27 EST 2005


Attached is a patch to keep the reference to the delegates. Also an 
improvement on the former patch which only changes domains when needed.

Scott


Scott Mohekey wrote:

> It seems I spoke too soon.
>
> Now I get the following assertion:
>
> Unmanaged code called delegate of type 
> System.Drawing.GDIPlus/GdiPlusStreamHelper.StreamPutBytesImpl which 
> was already garbage collected.
> See http://www.go-mono.com/delegate.html for an explanation and ways 
> to fix this.
> aborting...
>
> However, I think this could be due to GdiPlusStreamHelper in 
> gdipFunctions.cs not keeping references to the delegates. I'll check 
> this now.
>
> Scott.
>

Index: mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs
===================================================================
--- mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs    
(revision 41126)
+++ mcs/class/System.Drawing/System.Drawing/gdipFunctions.cs    (working 
copy)
@@ -1493,6 +1493,11 @@
                internal class GdiPlusStreamHelper
                {
                        public Stream stream;
+                       private StreamGetBytesDelegate getBytesDelegate 
= null;
+                       private StreamSeekDelegate seekDelegate = null;
+                       private StreamPutBytesDelegate putBytesDelegate 
= null;
+                       private StreamCloseDelegate closeDelegate = null;
+                       private StreamSizeDelegate sizeDelegate = null;

                        public GdiPlusStreamHelper (Stream s)
                        {
@@ -1536,8 +1541,13 @@

                        public StreamGetBytesDelegate GetBytesDelegate {
                                get {
-                                       if (stream != null && 
stream.CanRead)
-                                               return new 
StreamGetBytesDelegate (StreamGetBytesImpl);
+                                       if (stream != null && 
stream.CanRead) {
+                                               lock (this) {
+                                                       if (null == 
getBytesDelegate)
+                                                               
getBytesDelegate = new StreamGetBytesDelegate (StreamGetBytesImpl);
+                                               }
+                                               return getBytesDelegate;
+                                       }
                                        return null;
                                }
                        }
@@ -1560,8 +1570,13 @@

                        public StreamSeekDelegate SeekDelegate {
                                get {
-                                       if (stream != null && 
stream.CanSeek)
-                                               return new 
StreamSeekDelegate (StreamSeekImpl);
+                                       if (stream != null && 
stream.CanSeek) {
+                                               lock (this) {
+                                                       if (null == 
seekDelegate)
+                                                               
seekDelegate = new StreamSeekDelegate (StreamSeekImpl);
+                                               }
+                                               return seekDelegate;
+                                       }
                                        return null;
                                }
                        }
@@ -1576,8 +1591,13 @@

                        public StreamPutBytesDelegate PutBytesDelegate {
                                get {
-                                       if (stream != null && 
stream.CanWrite)
-                                               return new 
StreamPutBytesDelegate (StreamPutBytesImpl);
+                                       if (stream != null && 
stream.CanWrite) {
+                                               lock (this) {
+                                                       if (null == 
putBytesDelegate)
+                                                               
putBytesDelegate = new StreamPutBytesDelegate (StreamPutBytesImpl);
+                                               }
+                                               return putBytesDelegate;
+                                       }
                                        return null;
                                }
                        }
@@ -1589,8 +1609,13 @@

                        public StreamCloseDelegate CloseDelegate {
                                get {
-                                       if (stream != null)
-                                               return new 
StreamCloseDelegate (StreamCloseImpl);
+                                       if (stream != null) {
+                                               lock (this) {
+                                                       if (null == 
closeDelegate)
+                                                               
closeDelegate = new StreamCloseDelegate (StreamCloseImpl);
+                                               }
+                                               return closeDelegate;
+                                       }
                                        return null;
                                }
                        }
@@ -1602,8 +1627,13 @@

                        public StreamSizeDelegate SizeDelegate {
                                get {
-                                       if (stream != null)
-                                               return new 
StreamSizeDelegate (StreamSizeImpl);
+                                       if (stream != null) {
+                                               lock (this) {
+                                                       if (null == 
sizeDelegate)
+                                                               
sizeDelegate = new StreamSizeDelegate (StreamSizeImpl);
+                                               }
+                                               return sizeDelegate;
+                                       }
                                        return null;
                                }
                        }

Index: mcs/class/System.Drawing/System.Drawing/Image.cs
===================================================================
--- mcs/class/System.Drawing/System.Drawing/Image.cs    (revision 41126)
+++ mcs/class/System.Drawing/System.Drawing/Image.cs    (working copy)
@@ -55,8 +55,8 @@

        internal IntPtr nativeObject = IntPtr.Zero;
        ColorPalette colorPalette;
+       private GDIPlus.GdiPlusStreamHelper sh;

-
        // constructor
        internal  Image()
        {
@@ -198,7 +198,7 @@
                        // We use a custom API for this, because there's 
no easy way
                        // to get the Stream down to libgdiplus.  So, we 
wrap the stream
                        // with a set of delegates.
-                       GDIPlus.GdiPlusStreamHelper sh = new 
GDIPlus.GdiPlusStreamHelper (stream);
+                       sh = new GDIPlus.GdiPlusStreamHelper (stream);
                        IntPtr imagePtr;

                        Status st = 
GDIPlus.GdipLoadImageFromDelegate_linux (sh.GetBytesDelegate, 
sh.PutBytesDelegate,

Index: mono/mono/metadata/gc.c
===================================================================
--- mono/mono/metadata/gc.c     (revision 41118)
+++ mono/mono/metadata/gc.c     (working copy)
@@ -81,8 +81,19 @@
         */
        if (o->vtable->klass->delegate) {
                MonoDelegate* del = (MonoDelegate*)o;
-               if (del->delegate_trampoline)
+               MonoDomain* domain = mono_domain_get ();
+
+               if (del->delegate_trampoline) {
+                       if (domain != o->vtable->domain) {
+                               mono_domain_set_internal 
(o->vtable->domain);
+                       }
+
                        mono_delegate_free_ftnptr ((MonoDelegate*)o);
+
+                       if (domain != o->vtable->domain) {
+                               mono_domain_set_internal (domain);
+                       }
+               }
                return;
        }
        if (o->vtable->klass == mono_get_thread_class ())




More information about the Mono-devel-list mailing list