Skip to content

Commit d684356

Browse files
committed
8262731: [macOS] Exception from "Printable.print" is swallowed during "PrinterJob.print"
Backport-of: c0b4407d09a7bf9f15553dc5344b1e354b150d57
1 parent a32d2ee commit d684356

2 files changed

Lines changed: 169 additions & 9 deletions

File tree

src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.net.URI;
3434
import java.security.AccessController;
3535
import java.security.PrivilegedAction;
36+
import java.util.concurrent.atomic.AtomicReference;
3637

3738
import javax.print.*;
3839
import javax.print.attribute.PrintRequestAttributeSet;
@@ -60,6 +61,7 @@ public final class CPrinterJob extends RasterPrinterJob {
6061
private static String sShouldNotReachHere = "Should not reach here.";
6162

6263
private volatile SecondaryLoop printingLoop;
64+
private AtomicReference<Throwable> printErrorRef = new AtomicReference<>();
6365

6466
private boolean noDefaultPrinter = false;
6567

@@ -323,6 +325,7 @@ public void print(PrintRequestAttributeSet attributes) throws PrinterException {
323325
performingPrinting = true;
324326
userCancelled = false;
325327
}
328+
printErrorRef.set(null);
326329

327330
//Add support for PageRange
328331
PageRanges pr = (attributes == null) ? null
@@ -381,6 +384,15 @@ public SecondaryLoop run() {
381384
if (printingLoop != null) {
382385
printingLoop.exit();
383386
}
387+
388+
Throwable printError = printErrorRef.getAndSet(null);
389+
if (printError != null) {
390+
if (printError instanceof PrinterException) {
391+
throw (PrinterException) printError;
392+
}
393+
throw (PrinterException)
394+
new PrinterException().initCause(printError);
395+
}
384396
}
385397

386398
// Normalize the collated, # copies, numPages, first/last pages. Need to
@@ -786,22 +798,36 @@ private Object[] getPageformatPrintablePeekgraphics(final int pageIndex) {
786798
private Rectangle2D printAndGetPageFormatArea(final Printable printable, final Graphics graphics, final PageFormat pageFormat, final int pageIndex) {
787799
final Rectangle2D[] ret = new Rectangle2D[1];
788800

789-
Runnable r = new Runnable() { public void run() { synchronized(ret) {
790-
try {
791-
int pageResult = printable.print(graphics, pageFormat, pageIndex);
792-
if (pageResult != Printable.NO_SUCH_PAGE) {
793-
ret[0] = getPageFormatArea(pageFormat);
801+
Runnable r = new Runnable() {
802+
@Override
803+
public void run() {
804+
synchronized (ret) {
805+
try {
806+
int pageResult = printable.print(
807+
graphics, pageFormat, pageIndex);
808+
if (pageResult != Printable.NO_SUCH_PAGE) {
809+
ret[0] = getPageFormatArea(pageFormat);
810+
}
811+
} catch (Throwable t) {
812+
printErrorRef.compareAndSet(null, t);
813+
}
794814
}
795-
} catch (Exception e) {} // Original code bailed on any exception
796-
}}};
815+
}
816+
};
797817

798818
if (onEventThread) {
799-
try { EventQueue.invokeAndWait(r); } catch (Exception e) { e.printStackTrace(); }
819+
try {
820+
EventQueue.invokeAndWait(r);
821+
} catch (Throwable t) {
822+
printErrorRef.compareAndSet(null, t);
823+
}
800824
} else {
801825
r.run();
802826
}
803827

804-
synchronized(ret) { return ret[0]; }
828+
synchronized (ret) {
829+
return ret[0];
830+
}
805831
}
806832

807833
// upcall from native
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/* @test
25+
@bug 8262731
26+
@key headful printer
27+
@summary Verify that "PrinterJob.print" throws the expected exception,
28+
if "Printable.print" throws an exception.
29+
@run main ExceptionFromPrintableIsIgnoredTest MAIN PE
30+
@run main ExceptionFromPrintableIsIgnoredTest MAIN RE
31+
@run main ExceptionFromPrintableIsIgnoredTest EDT PE
32+
@run main ExceptionFromPrintableIsIgnoredTest EDT RE
33+
*/
34+
35+
import java.awt.Graphics;
36+
import java.awt.print.PageFormat;
37+
import java.awt.print.Printable;
38+
import java.awt.print.PrinterException;
39+
import java.awt.print.PrinterJob;
40+
import java.lang.reflect.InvocationTargetException;
41+
import javax.swing.SwingUtilities;
42+
43+
public class ExceptionFromPrintableIsIgnoredTest {
44+
private enum TestThreadType {MAIN, EDT}
45+
private enum TestExceptionType {PE, RE}
46+
47+
private volatile Throwable printError;
48+
49+
public static void main(String[] args) {
50+
if (args.length < 2) {
51+
throw new RuntimeException("Two arguments are expected:"
52+
+ " test thread type and test exception type.");
53+
}
54+
55+
new ExceptionFromPrintableIsIgnoredTest(
56+
TestThreadType.valueOf(args[0]),
57+
TestExceptionType.valueOf(args[1]));
58+
}
59+
60+
public ExceptionFromPrintableIsIgnoredTest(
61+
final TestThreadType threadType,
62+
final TestExceptionType exceptionType) {
63+
System.out.println(String.format(
64+
"Test started. threadType='%s', exceptionType='%s'",
65+
threadType, exceptionType));
66+
67+
String osName = System.getProperty("os.name");
68+
boolean isOSX = osName.toLowerCase().startsWith("mac");
69+
if ((exceptionType == TestExceptionType.RE) && !isOSX) {
70+
System.out.println(
71+
"Currently this test scenario can be verified only on macOS.");
72+
return;
73+
}
74+
75+
printError = null;
76+
77+
if (threadType == TestThreadType.MAIN) {
78+
runTest(exceptionType);
79+
} else if (threadType == TestThreadType.EDT) {
80+
try {
81+
SwingUtilities.invokeAndWait(new Runnable() {
82+
@Override
83+
public void run() {
84+
runTest(exceptionType);
85+
}
86+
});
87+
} catch (InterruptedException | InvocationTargetException e) {
88+
throw new RuntimeException(e);
89+
}
90+
}
91+
92+
if (printError == null) {
93+
throw new RuntimeException("No exception was thrown.");
94+
} else if (!(printError instanceof PrinterException)) {
95+
throw new RuntimeException("Unexpected exception was thrown.");
96+
}
97+
System.out.println("Test passed.");
98+
}
99+
100+
private void runTest(final TestExceptionType exceptionType) {
101+
PrinterJob job = PrinterJob.getPrinterJob();
102+
if (job.getPrintService() == null) {
103+
System.out.println("No printers are available.");
104+
return;
105+
}
106+
107+
job.setPrintable(new Printable() {
108+
@Override
109+
public int print(Graphics graphics, PageFormat pageFormat,
110+
int pageIndex) throws PrinterException {
111+
if (pageIndex > 1) {
112+
return NO_SUCH_PAGE;
113+
}
114+
if (exceptionType == TestExceptionType.PE) {
115+
throw new PrinterException(
116+
"Exception from 'Printable.print'.");
117+
} else if (exceptionType == TestExceptionType.RE) {
118+
throw new RuntimeException(
119+
"Exception from 'Printable.print'.");
120+
}
121+
return PAGE_EXISTS;
122+
}
123+
});
124+
125+
try {
126+
job.print();
127+
} catch (Throwable t) {
128+
printError = t;
129+
130+
System.out.println("'PrinterJob.print' threw the exception:");
131+
t.printStackTrace(System.out);
132+
}
133+
}
134+
}

0 commit comments

Comments
 (0)