Hi,

I was seeing deadlocks in some cases with ComponentGraphics.drawImage().
ComponentGraphics takes the gdk lock and then calls super.drawImage().
But in some cases when the image isn't a BufferedImage CairoGraphics
would recurse into drawImage() again. And since the gdk lock isn't
reentrant that would cause a deadlock. There was a second problem if the
image was the error image, in that case it wouldn't have a ImageProducer
and later on in CairoGraphics.drawImage() an Exception would be thrown.
In that case the gdk lock would never be released. To prevent against
such situations this patch also moves all operations that have to
operate with the gdk lock held into a try-finally block to make sure the
lock is always released.

2006-06-10  Mark Wielaard  <[EMAIL PROTECTED]>

    * gnu/java/awt/peer/gtk/CairoGraphics2D.java (drawImage):
    Don't recurse, return false if not an BufferedImage and no image
    source available.
    * gnu/java/awt/peer/gtk/ComponentGraphics.java (draw): Add
    end_gdk_drawing() to finally block.
    (fill): Likewise.
    (drawRenderedImage): Likewise.
    (drawImage): Likewise.
    (drawGlyphVector): Likewise.

Does this look sane?

Thanks,

Mark
Index: gnu/java/awt/peer/gtk/CairoGraphics2D.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/CairoGraphics2D.java,v
retrieving revision 1.18
diff -u -r1.18 CairoGraphics2D.java
--- gnu/java/awt/peer/gtk/CairoGraphics2D.java	10 Jun 2006 10:33:17 -0000	1.18
+++ gnu/java/awt/peer/gtk/CairoGraphics2D.java	10 Jun 2006 21:14:49 -0000
@@ -79,6 +79,7 @@
 import java.awt.image.DataBufferInt;
 import java.awt.image.DirectColorModel;
 import java.awt.image.ImageObserver;
+import java.awt.image.ImageProducer;
 import java.awt.image.ImagingOpException;
 import java.awt.image.MultiPixelPackedSampleModel;
 import java.awt.image.Raster;
@@ -1100,11 +1101,14 @@
 				     + xform.toString());
       }
 
-    // Unrecognized image - convert to a BufferedImage and come back.
+    // Unrecognized image - convert to a BufferedImage
     if( !(img instanceof BufferedImage) )
-      return this.drawImage(Toolkit.getDefaultToolkit().
-			    createImage(img.getSource()),
-			    xform, bgcolor, obs);
+      {
+	ImageProducer source = img.getSource();
+	if (source == null)
+	  return false;
+	img = Toolkit.getDefaultToolkit().createImage(source);
+      }
 
     BufferedImage b = (BufferedImage) img;
     DataBuffer db;
Index: gnu/java/awt/peer/gtk/ComponentGraphics.java
===================================================================
RCS file: /cvsroot/classpath/classpath/gnu/java/awt/peer/gtk/ComponentGraphics.java,v
retrieving revision 1.12
diff -u -r1.12 ComponentGraphics.java
--- gnu/java/awt/peer/gtk/ComponentGraphics.java	10 Jun 2006 10:33:18 -0000	1.12
+++ gnu/java/awt/peer/gtk/ComponentGraphics.java	10 Jun 2006 21:14:49 -0000
@@ -181,38 +181,69 @@
   public void draw(Shape s)
   {
     start_gdk_drawing();
-    super.draw(s);
-    end_gdk_drawing();
+    try
+      {
+	super.draw(s);
+      }
+    finally
+      {
+	end_gdk_drawing();
+      }
   }
 
   public void fill(Shape s)
   {
     start_gdk_drawing();
-    super.fill(s);
-    end_gdk_drawing();
+    try
+      {
+	super.fill(s);
+      }
+    finally
+      {
+	end_gdk_drawing();
+      }
   }
 
   public void drawRenderedImage(RenderedImage image, AffineTransform xform)
   {
     start_gdk_drawing();
-    super.drawRenderedImage(image, xform);
-    end_gdk_drawing();
+    try
+      {
+	super.drawRenderedImage(image, xform);
+      }
+    finally
+      {
+	end_gdk_drawing();
+      }
   }
 
   protected boolean drawImage(Image img, AffineTransform xform,
 			      Color bgcolor, ImageObserver obs)
   {
+    boolean rv;
     start_gdk_drawing();
-    boolean rv = super.drawImage(img, xform, bgcolor, obs);
-    end_gdk_drawing();
+    try
+      {
+	rv = super.drawImage(img, xform, bgcolor, obs);
+      }
+    finally
+      {
+	end_gdk_drawing();
+      }
     return rv;
   }
 
   public void drawGlyphVector(GlyphVector gv, float x, float y)
   {
     start_gdk_drawing();
-    super.drawGlyphVector(gv, x, y);
-    end_gdk_drawing();
+    try
+      {
+	super.drawGlyphVector(gv, x, y);
+      }
+    finally
+      {
+	end_gdk_drawing();
+      }
   }
   
   public boolean drawImage(Image img, int x, int y, ImageObserver observer)

Reply via email to