From 3cf1d6ac1512e1c1aaa7bce065cf6cb40b7a465b Mon Sep 17 00:00:00 2001 From: Oleg Pekhovskiy Date: Wed, 16 Nov 2011 15:40:59 +0400 Subject: [PATCH] 7108598: Pogo Table Games freeze with JDK 7 Reviewed-by: art, ant --- jdk/src/share/classes/java/awt/Component.java | 5 +- jdk/src/share/classes/java/awt/Container.java | 6 +- .../PaintSetEnabledDeadlock.java | 175 ++++++++++++++++++ 3 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index 0440d87085d..550ba7654b0 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -666,9 +666,10 @@ public abstract class Component implements ImageObserver, MenuContainer, * 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 --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index c59aa90bc5f..03b0f7faa04 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -1950,7 +1950,7 @@ public class Container extends Component { */ public void paint(Graphics g) { if (isShowing()) { - synchronized (this) { + synchronized (getObjectLock()) { if (printing) { if (printingThreads.contains(Thread.currentThread())) { return; @@ -2004,7 +2004,7 @@ public class Container extends Component { if (isShowing()) { Thread t = Thread.currentThread(); try { - synchronized (this) { + synchronized (getObjectLock()) { if (printingThreads == null) { printingThreads = new HashSet(); } @@ -2013,7 +2013,7 @@ public class Container extends Component { } super.print(g); // By default, Component.print() calls paint() } finally { - synchronized (this) { + synchronized (getObjectLock()) { printingThreads.remove(t); printing = !printingThreads.isEmpty(); } diff --git a/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java b/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java new file mode 100644 index 00000000000..294f455567b --- /dev/null +++ b/jdk/test/java/awt/print/PaintSetEnabledDeadlock/PaintSetEnabledDeadlock.java @@ -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(); + } + } +}