Skip to content

Commit

Permalink
JBR-6117 Wayland: JVM shutdown hang
Browse files Browse the repository at this point in the history
  • Loading branch information
mkartashev authored and jbrbot committed Nov 8, 2024
1 parent ba1b5ce commit 20b2eeb
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/java.desktop/unix/classes/sun/awt/wl/WLComponentPeer.java
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,12 @@ public FontMetrics getFontMetrics(Font font) {

@Override
public void dispose() {
SurfaceData oldData = surfaceData;
surfaceData = null;
if (oldData != null) {
oldData.invalidate();
}
WLToolkit.targetDisposedPeer(target, this);
performLocked(() -> {
assert(!isVisible());
nativeDisposeFrame(nativePtr);
Expand Down
3 changes: 3 additions & 0 deletions src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import jdk.internal.misc.InnocuousThread;
import sun.awt.AWTAccessor;
import sun.awt.AWTAutoShutdown;
import sun.awt.AppContext;
import sun.awt.LightweightFrame;
import sun.awt.PeerEvent;
Expand Down Expand Up @@ -204,12 +205,14 @@ private void dispatchNonDefaultQueues() {
@Override
public void run() {
while(true) {
AWTAutoShutdown.notifyToolkitThreadFree(); // will now wait for events
int result = readEvents();
if (result == READ_RESULT_ERROR) {
log.severe("Wayland protocol I/O error");
// TODO: display disconnect handling here?
break;
} else if (result == READ_RESULT_FINISHED_WITH_EVENTS) {
AWTAutoShutdown.notifyToolkitThreadBusy(); // busy processing events
SunToolkit.postEvent(AppContext.getAppContext(), new PeerEvent(this, () -> {
WLToolkit.awtLock();
try {
Expand Down
1 change: 1 addition & 0 deletions test/jdk/TEST.groups
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,7 @@ jdk_since_checks = \
# Wayland tests to be executed with -Dawt.toolkit.name=WLToolkit
jdk_awt_wayland = \
:jdk_awt \
jb/java/awt/wayland \
-com/apple/eawt \
-com/apple/laf \
-sun/awt \
Expand Down
141 changes: 141 additions & 0 deletions test/jdk/jb/java/awt/wayland/WLShutdownTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, JetBrains s.r.o.. 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.
*/

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CountDownLatch;

/*
* @test
* @summary Verifies that the program finishes after disposing of JFrame
* @run main WLShutdownTest
*/
public class WLShutdownTest {
private static JFrame frame = null;

public static void main(String[] args) throws Exception {
final CountDownLatch latchShownFrame = new CountDownLatch(1);
final CountDownLatch latchClosedFrame = new CountDownLatch(1);

SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
frame = new JFrame("TEST");

frame.addComponentListener(new ComponentAdapter() {
@Override
public void componentShown(ComponentEvent e) {
latchShownFrame.countDown();
}
});
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
latchClosedFrame.countDown();
}
});

JPanel panel = new JPanel() {
int n = 0;

@Override
protected void paintComponent(Graphics g) {
System.out.print("P");
g.setColor((n++ % 2 == 0) ? Color.RED : Color.BLUE);
g.fillRect(0, 0, getWidth(), getHeight());
System.out.print("Q");
}
};

panel.setPreferredSize(new Dimension(800, 800));
panel.setBackground(Color.BLACK);
frame.add(panel);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
System.out.print(">>");
}
});

// Wait frame to be shown:
latchShownFrame.await();

System.out.print(":>>");

final long startTime = System.currentTimeMillis();
final long endTime = startTime + 3000;

// Start 1st measurement:
repaint();

for (; ; ) {
System.out.print(".");

repaint();

if (System.currentTimeMillis() >= endTime) {
break;
}
sleep();
} // end measurements

SwingUtilities.invokeAndWait(() -> {
frame.setVisible(false);
frame.dispose();
});

latchClosedFrame.await();
System.out.print("<<\n");

frame = null; // free static ref: gc
System.out.println("Waiting AWT to shutdown JVM soon ...");
}


static void repaint() throws Exception {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
frame.repaint();
}
});
}

static void sleep() {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace(System.err);
}
}
}

0 comments on commit 20b2eeb

Please sign in to comment.