Issue1256374
Created on 2005-08-11.03:33:48 by paulfernhout, last changed 2013-02-07.22:59:53 by fwierzbicki.
Messages | |||
---|---|---|---|
msg2460 (view) | Author: Paul Fernhout (paulfernhout) | Date: 2005-08-11.03:33:48 | |
The sys.excepthook functionality does not appear to catch Swing generated exceptions, only exceptions generated from straight Jython. This is perhaps because Swing events happen in a different thread. As discussed on the Jython users list on 2003-12-01: "Re: sys.excepthook doesn't affect Swing exception handling " by (Randolph Brown) http://sourceforge.net/mailarchive/message.php?msg_id=6710944 in order to catch Swing exceptions, there needs to be some special handling code written in Java. Apparently there is a hack of: System.setProperty("sun.awt.exception.handler", "full.name.of.your.Class"); to do so. For reference, that hack is "temporary", according to: http://www.jguru.com/faq/view.jsp?EID=427279 "Note: This method is a temporary hack to work around the absence of a real API that provides the ability to replace the event-dispatch thread. The magic "sun.awt.exception.handler" property will be removed in a future release." Clearly this approach has worked for several versions of Java, but it would be something that might need future maintenance if Java changesthe API for doing such hooks. Still, based on that idea, I put together the following change to the Jython code in case it is of use to anyone. First, here is a test case that shows the latest Jython not handling sys.excepthook in response to code activated from a menu event. (All three of 2.1, 2.2a, and the latest CVS seem to have this issue). ==== jython_swing_excepthook_test.py === import sys from javax.swing import JFrame, JMenuBar, JMenu, JMenuItem class TestFrame(JFrame): def __init__(self): JFrame.__init__(self, "Jython excepthook Test") self.setBounds(200, 200, 400, 300) menuBar = JMenuBar() self.setJMenuBar(menuBar) fileMenu = JMenu("File") menuBar.add(fileMenu) menuItem = JMenuItem("Test", actionPerformed=self.test) fileMenu.add(menuItem) def test(self, event=None): print "test exception -- divide by zero attempt follows" x = 1 / 0 print "divide by zero done" def MyExceptHook(type, value, traceback): print "my exception handler:", type, value, traceback sys.excepthook = MyExceptHook frame = TestFrame() frame.setVisible(1) # now try the menu item # and you will get default exception handler, # not my exception handler # unless you apply patch ====================== Here is a patch that makes the exception handler be called for the latest Jython from CVS. The patch consists of a new class file (AwtExceptionHandler.java), and a one line addition to an existing class file (jython.java). ==== AwtExceptionHandler.java ==== package org.python.util; import org.python.core.Py; public class AwtExceptionHandler { public void handle(Throwable t) { // This indirectly calls the excepthook if it exists Py.printException(t, null, null); } } ========================= One line added to jython.java below to hook up the class... ==== jython.java changes ===== public class jython ... public static void main(String[] args) { + System.setProperty("sun.awt.exception.handler", "org.python.util.AwtExceptionHandler"); ... ===================== Now this patch has not been heavily tested; I just got it working as a proof of concept. Also the "System.setProperty" line may not be in the best place to link it in; I suspect there is a more general place to put it and perhaps it may not be called when Jython is used in other ways? I just downloaded the Jython source recently, and this internal exception stuff is bound to be tricky, and I don't know the Jython codebase, so think of this as just a pointer in one possible direction for a bug fix to be mulled over, rather than the final answer. There may perhaps be other Java exceptions still not caught. Also, I was working in Java 1.4.2 (GNU/Linux Blackdown-1.4.2-02), perhaps Java 1.5 has other options? For example, a newly added feature in 1.5 (though I'm currently using 1.4.2, so it is unavailable to me) is this function: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html "java.lang Class Thread static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, and no other handler has been defined for that thread." Also, I was not too sure about passing those two nulls to "Py.printException(t, null, null);". Maybe they could be something else? Anyway, there was discussion in that thread above from 2003-12-01 of making a flag somewhere to set this behavior and questioning what the default expectation should be. Personally I think an excepthook in Python should always fire on any exception, but I could see not changing default behavior if people rely on it already, especially if they call Jython from Java and expect Java to be in control of things. |
|||
msg7363 (view) | Author: Frank Wierzbicki (fwierzbicki) | Date: 2012-08-10.17:53:34 | |
Paul are you still around and interested in pushing this forward? If so uploading a patch and perhaps some tests would be much easier to evaluate than embedded code. Sorry that this has lingered for so long without a reply :( |
|||
msg7389 (view) | Author: Paul Fernhout (paulfernhout) | Date: 2012-08-11.17:54:59 | |
Frank, First, thanks for all the great work you've done with Jython, and thanks for getting around to snipping off all these loose ends. I really enjoyed my time using Jython, but I've been doing mostly straight Java work myself lately, so I don't have time or interest to push this issue forward much myself at this point, sorry. This issue was with the Jython version from about seven years ago and running on Java 1.4 (the issue being posted in 2005), so I am not sure how reproducible this issue is at this point or whether the suggestion for resolving it is the best one anymore. However, here are a few comments on the general issue that might be useful to any Jython user encountering this issue or trying to resolve it in some way. These comments suggest you can just mark the issue closed (at least with a likely workaround) at this point. Later versions of Java have new ways of dealing with uncaught exceptions, like in Java 5, which introduced setDefaultUncaughtExceptionHandler for Thread: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler%28java.lang.Thread.UncaughtExceptionHandler%29 Still, since the Swing thread has its own exception handler that prints to the console, something else might still need to be done for a Java-based application to intercept such Swing exceptions. Apparently, according to this StackOverflow question, you still need to set the "sun.awt.exception.hander" property in some situations, even in Java 6: http://stackoverflow.com/questions/5794472/why-bother-with-setting-the-sun-awt-exception-handler-property So, I don't think using the above by itself would fix this issue. Still, clearly you can handle Swing Event Dispatch Thread exceptions from plain Java, like discussed in these Stack Overflow questions: http://stackoverflow.com/questions/4448523/how-can-i-catch-event-dispatch-thread-edt-exceptions http://stackoverflow.com/questions/95767/how-can-i-catch-awt-thread-exceptions-in-java It is suggested in an answer at the last link that Java7 may have fixed this, so that the uncaught exception handler will cover everything. I'm also not quite sure what happens if you try to get hold of the EDT instance directly and call setUncaughtExceptionHandler directly (perhaps by reflection if needed)? However, it seems like Java6 will not allow that, according to this JDK bug report / feature request? http://bugs.sun.com/view_bug.do?bug_id=6791501 In any case, seven years later, I can hope this could be done entirely from Jython at this point for Java 5 or Java 6? Certainly I would expect it would work from Java 7. The big issue back then was that I could not figure out how to get a valid class name string to send into that call to System.setProperty which referenced a Jython-defined exception handler class. Otherwise, a Jython application could then just call System.setProperty directly of course (and that part of the patch probably did not have to be in Java even then). However, I have not tried the latest versions of Jython to know if you could define a class in such a way that the JVM would notice it later. If so, you could set the Event Dispatch Thread hook in the regular way for "sun.awt.exception.handler". But if Jython could do that now (or if perhaps it could do it then and I did not understand how to do that then), then there would be no need for the change I outlined back then. In that sense, maybe this was (or still is?) more a "bug" about the way Jython defined Java-accessible class names then? Or at least a "bug" in my understanding of how to to pass a string to Java with the full name of a Jython-defined class? You might be the best person to be able to answer off-hand whether a Jython-defined class could looked up by name in the current version of Jython. If there was a way to do that, and it worked when setting this System property, then this patch would be unneeded. Also, if a new Java-defined exception handling class was for some reason was needed in the end (I'm not sure how Java looks for named classes that are defined later), then it might be possible that a developer could include such a class in a Jar file in the classpath when starting Jython rather than by modifying the Jython codebase itself? I have not tried that though, but I would expect it might work. So, if using a jar file was combined with calling System.setProperty from Jython, I would think there is at the very least a workaround (although I have not tested that). I can wonder if there is also possible that this is an issue of timing -- that once the EDT is started in those earlier versions of Java, maybe it was too late to set that property? So, probably there are a few plausible workarounds for this issue (including just waiting for Java 7 to become mainstream). In that sense, it's fine by me if you just mark this issue closed. --Paul Fernhout http://www.pdfernhout.net/ ==== The biggest challenge of the 21st century is the irony of technologies of abundance in the hands of those thinking in terms of scarcity. |
|||
msg7393 (view) | Author: Frank Wierzbicki (fwierzbicki) | Date: 2012-08-13.18:18:13 | |
Paul: thanks for the extra details! Alex: I assigned this one to you - but really just to get your opinion since you know so much about Jython/Swing interaction. Hopefully you have some comments or suggestions on what we should do here (if anything). Perhaps it isn't even a bug anymore? |
|||
msg7452 (view) | Author: Alex Grönholm (alex.gronholm) | Date: 2012-09-01.16:38:20 | |
I've been wondering if it's okay for Jython to hijack all the Swing exceptions. In a 100% Jython-Swing app that's fine I suppose, but what of apps that only embed Jython? |
|||
msg7490 (view) | Author: Alex Grönholm (alex.gronholm) | Date: 2012-10-27.22:53:53 | |
The reason this has taken so long is probably as follows: Jython can be used either by directly launching it or from embedding it into an existing application. If Jython is launched directly, then sure, by all means we should handle all AWT exceptions through the exception hook if it exists. However, if Jython is embedded into the application, it may not be desirable in all situations to mess with the default exception handler. But I would still expect exceptions in Jython code to be handled by the exception hook, even when they're run in the Event Dispatch Thread! However, Java AWT code not called from Jython that throws an exception should not be redirected to the Jython exception hook. Is this even possible to accomplish? I'm such a noob in Jython development that I don't know where to even begin to work on such a solution. Bottom line: IMHO this patch is too naïve -- a more sophisticated solution is needed. |
|||
msg7643 (view) | Author: Frank Wierzbicki (fwierzbicki) | Date: 2013-02-07.22:59:53 | |
Alex: Since you are our resident Swing expert I'd say we close this. |
History | |||
---|---|---|---|
Date | User | Action | Args |
2013-02-07 22:59:53 | fwierzbicki | set | status: open -> closed resolution: out of date messages: + msg7643 |
2012-10-27 22:53:54 | alex.gronholm | set | messages: + msg7490 |
2012-09-01 16:38:21 | alex.gronholm | set | messages: + msg7452 |
2012-08-13 18:18:13 | fwierzbicki | set | assignee: alex.gronholm messages: + msg7393 nosy: + alex.gronholm |
2012-08-11 17:55:01 | paulfernhout | set | messages: + msg7389 |
2012-08-10 17:53:35 | fwierzbicki | set | nosy:
+ fwierzbicki messages: + msg7363 |
2008-12-14 17:46:34 | fwierzbicki | set | components: + Core, - None |
2005-08-11 03:33:48 | paulfernhout | create |
Supported by Python Software Foundation,
Powered by Roundup