1 /*
2  * Copyright (c) 2013, 2014, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package sun.awt.X11;
26 
27 import java.security.AccessController;
28 import sun.awt.SunToolkit;
29 import sun.security.action.GetBooleanAction;
30 import sun.util.logging.PlatformLogger;
31 
32 /**
33  * This class contains code of the global toolkit error handler, exposes static
34  * methods which allow to set and unset synthetic error handlers.
35  */
36 public final class XErrorHandlerUtil {
37     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XErrorHandlerUtil");
38 
39     /**
40      * The connection to X11 window server.
41      */
42     private static long display;
43 
44     /**
45      * Error handler at the moment of {@code XErrorHandlerUtil} initialization.
46      */
47     private static long saved_error_handler;
48 
49     /**
50      * XErrorEvent being handled.
51      */
52     static volatile XErrorEvent saved_error;
53 
54     /**
55      * Current error handler or null if no error handler is set.
56      */
57     private static XErrorHandler current_error_handler;
58 
59     /**
60      * Value of sun.awt.noisyerrorhandler system property.
61      */
62     private static boolean noisyAwtHandler = AccessController.doPrivileged(
63         new GetBooleanAction("sun.awt.noisyerrorhandler"));
64 
65     /**
66      * The flag indicating that {@code init} was called already.
67      */
68     private static boolean initPassed;
69 
70     /**
71      * Guarantees that no instance of this class can be created.
72      */
XErrorHandlerUtil()73     private XErrorHandlerUtil() {}
74 
75     /**
76      * Sets the toolkit global error handler, stores the connection to X11 server,
77      * which will be used during an error handling process. This method is called
78      * once from {@code awt_init_Display} function defined in {@code awt_GraphicsEnv.c}
79      * file immediately after the connection to X11 window server is opened.
80      * @param display the connection to X11 server which should be stored
81      */
init(long display)82     private static void init(long display) {
83         SunToolkit.awtLock();
84         try {
85             if (!initPassed) {
86                 XErrorHandlerUtil.display = display;
87                 saved_error_handler = XlibWrapper.SetToolkitErrorHandler();
88                 initPassed = true;
89             }
90         } finally {
91             SunToolkit.awtUnlock();
92         }
93     }
94 
95     /**
96      * Sets a synthetic error handler. Must be called with the acquired AWT lock.
97      * @param handler the synthetic error handler to set
98      */
WITH_XERROR_HANDLER(XErrorHandler handler)99     public static void WITH_XERROR_HANDLER(XErrorHandler handler) {
100         XSync();
101         saved_error = null;
102         current_error_handler = handler;
103     }
104 
105     /**
106      * Unsets a current synthetic error handler. Must be called with the acquired AWT lock.
107      */
RESTORE_XERROR_HANDLER()108     public static void RESTORE_XERROR_HANDLER() {
109         // Wait until all requests are processed by the X server
110         // and only then uninstall the error handler.
111         XSync();
112         current_error_handler = null;
113     }
114 
115     /**
116      * Should be called under LOCK.
117      */
SAVED_XERROR_HANDLER(long display, XErrorEvent error)118     public static int SAVED_XERROR_HANDLER(long display, XErrorEvent error) {
119         if (saved_error_handler != 0) {
120             // Default XErrorHandler may just terminate the process. Don't call it.
121             // return XlibWrapper.CallErrorHandler(saved_error_handler, display, error.pData);
122         }
123         if (log.isLoggable(PlatformLogger.Level.FINE)) {
124             log.fine("Unhandled XErrorEvent: " +
125                 "id=" + error.get_resourceid() + ", " +
126                 "serial=" + error.get_serial() + ", " +
127                 "ec=" + error.get_error_code() + ", " +
128                 "rc=" + error.get_request_code() + ", " +
129                 "mc=" + error.get_minor_code());
130         }
131         return 0;
132     }
133 
134     /**
135      * Called from the native code when an error occurs.
136      */
globalErrorHandler(long display, long event_ptr)137     private static int globalErrorHandler(long display, long event_ptr) {
138         if (noisyAwtHandler) {
139             XlibWrapper.PrintXErrorEvent(display, event_ptr);
140         }
141         XErrorEvent event = new XErrorEvent(event_ptr);
142         saved_error = event;
143         try {
144             if (current_error_handler != null) {
145                 return current_error_handler.handleError(display, event);
146             } else {
147                 return SAVED_XERROR_HANDLER(display, event);
148             }
149         } catch (Throwable z) {
150             log.fine("Error in GlobalErrorHandler", z);
151         }
152         return 0;
153     }
154 
XSync()155     private static void XSync() {
156         SunToolkit.awtLock();
157         try {
158             XlibWrapper.XSync(display, 0);
159         } finally {
160             SunToolkit.awtUnlock();
161         }
162     }
163 }
164