# HG changeset patch # User bagiras # Date 1321443659 -14400 # Node ID 1f244f2719d3fa5e0a1365c6ba1b682ea4a2a89e # Parent e753252dc8a9115f506390286893a1cf6022069a 7108598: Pogo Table Games freeze with JDK 7 Reviewed-by: art, ant diff -r e753252dc8a9 -r 1f244f2719d3 jdk/src/share/classes/java/awt/Component.java --- a/jdk/src/share/classes/java/awt/Component.java Sat Nov 12 04:13:38 2011 +0400 +++ b/jdk/src/share/classes/java/awt/Component.java Wed Nov 16 15:40:59 2011 +0400 @@ -666,9 +666,10 @@ * can lead to a deadlock if client code also uses synchronization * by a component object. For every such situation revealed we should * consider possibility of replacing "this" with the package private - * objectLock object introduced below. So far there're 2 issues known: + * objectLock object introduced below. So far there're 3 issues known: * - CR 6708322 (the getName/setName methods); - * - CR 6608764 (the PropertyChangeListener machinery). + * - CR 6608764 (the PropertyChangeListener machinery); + * - CR 7108598 (the Container.paint/KeyboardFocusManager.clearMostRecentFocusOwner methods). * * Note: this field is considered final, though readObject() prohibits * initializing final fields. diff -r e753252dc8a9 -r 1f244f2719d3 jdk/src/share/classes/java/awt/Container.java --- a/jdk/src/share/classes/java/awt/Container.java Sat Nov 12 04:13:38 2011 +0400 +++ b/jdk/src/share/classes/java/awt/Container.java Wed Nov 16 15:40:59 2011 +0400 @@ -1950,7 +1950,7 @@ */ public void paint(Graphics g) { if (isShowing()) { - synchronized (this) { + synchronized (getObjectLock()) { if (printing) { if (printingThreads.contains(Thread.currentThread())) { return; @@ -2004,7 +2004,7 @@ if (isShowing()) { Thread t = Thread.currentThread(); try { - synchronized (this) { + synchronized (getObjectLock()) { if (printingThreads == null) { printingThreads = new HashSet(); } @@ -2013,7 +2013,7 @@ } super.print(g); // By default, Component.print() calls paint() } finally { - synchronized (this) { + synchronized (getObjectLock()) { printingThreads.remove(t); printing = !printingThreads.isEmpty(); } diff -r e753252dc8a9 -r 1f244f2719d3 jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java Wed Nov 16 15:40:59 2011 +0400 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7108598 + * @summary Container.paint/KeyboardFocusManager.clearMostRecentFocusOwner methods deadlock + * @library ../../regtesthelpers + * @author Oleg Pekhovskiy + * @build Util + * @run main/timeout=20 PaintSetEnabledDeadlock + */ + +import java.awt.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Util; + +public class PaintSetEnabledDeadlock extends Frame { + + final TestPanel panel; + final Button button; + + public static void main(String[] args) { + PaintSetEnabledDeadlock frame = new PaintSetEnabledDeadlock(); + frame.setSize(200, 200); + frame.setVisible(true); + + Robot robot = Util.createRobot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + for (int i = 0; i < 20; ++i) { + Util.clickOnComp(frame.panel, robot); + Util.clickOnComp(frame.button, robot); + } + + frame.panel.stop(); + frame.dispose(); + + System.out.println("Test passed."); + } + + public PaintSetEnabledDeadlock() { + super("7108598 test"); + setLayout(new GridLayout(1, 2)); + addWindowListener(new WindowAdapter() { + + @Override + public void windowClosing(WindowEvent e) { + panel.stop(); + System.exit(0); + } + }); + panel = new TestPanel(); + add(panel); + button = new Button("Enable"); + button.addMouseListener(new MouseAdapter() { + + @Override + public void mousePressed(MouseEvent e) { + panel.setEnabled(true); + panel.sync(); + panel.repaint(); + } + }); + add(button); + } +} + +class TestPanel extends Panel implements Runnable { + + Image image = null; + Thread thread = null; + volatile boolean active = true; + final Object sync = new Object(); + Panel panel = this; + + public TestPanel() { + addMouseListener(new MouseAdapter() { + + @Override + public void mouseReleased(MouseEvent e) { + synchronized (panel) { + sync(); + panel.setEnabled(false); + } + panel.repaint(); + } + }); + thread = new Thread(this); + thread.start(); + } + + @Override + public void paint(Graphics paramGraphics) { + synchronized (getTreeLock()) { + Rectangle rect = getBounds(); + if (image == null) { + image = createImage(rect.width, rect.height); + } + + if (image != null) { + paramGraphics.drawImage(image, 0, 0, this); + } + } + } + + @Override + public void run() { + while (active) { + try { + synchronized (sync) { + sync.wait(); + } + } catch (InterruptedException ex) { + } + if (active) { + draw(); + } + } + } + + public void stop() { + active = false; + try { + synchronized (sync) { + sync.notify(); + } + synchronized (thread) { + thread.wait(); + } + } catch (InterruptedException ex) { + } + } + + public void draw() { + synchronized (getTreeLock()) { + if (image != null) { + Graphics localGraphics = image.getGraphics(); + Dimension size = getSize(); + localGraphics.setColor(isEnabled() ? Color.green : Color.red); + localGraphics.fillRect(0, 0, size.width, size.height); + super.paint(localGraphics); + localGraphics.dispose(); + getTreeLock().notifyAll(); + } + } + } + + public void sync() { + synchronized (sync) { + sync.notify(); + } + } +}