A shorter version is just to reassert at the end of catch e1. It is safer to just reassert as the last statement in the finally.
=== protected void loadImage(Image image) { MediaTracker mTracker = getTracker(); synchronized (mTracker) { int id = getNextID(); boolean wasInterrupted = false; mTracker.addImage(image, id); try { loadStatus = 0; mTracker.addImage(image, id); mTracker.waitForID(id, 0); } catch (InterruptedException e1) { wasInterrupted = true; try { mTracker.waitForID(id, 0); } catch (InterruptedException e2) { loadStatus = MediaTracker.ABORTED; } } finally { if (loadStatus == 0) { loadStatus = mTracker.statusID(id, false); } mTracker.removeImage(image, id); if (wasInterrupted) { Thread.currentThread().isInterrupted(); } } } } === Jason ________________________________________ From: Volodin, Vladislav <vladislav.volo...@sap.com> Sent: Tuesday, January 28, 2020 4:02 PM To: Jason Mehrens Cc: swing-dev@openjdk.java.net Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage This is a valid point, because I wasn’t sure that when the thread is interrupted, I handled the first exception, and my thought was that all other ‘wait’ calls (maybe in other threads) should get the same exception as well. And since I handled this exceptional case, I am restoring the interrupted status in case if I don’t know how to handle this exception the second time. } catch (InterruptedException e1) { try { mTracker.waitForID(id, 0); } catch (InterruptedException e2) { loadStatus = MediaTracker.ABORTED; Thread.currentThread().interrupt(); } If I restore the interrupted status BEFORE waitForID call, then this thread will immoderately fail. Should I restore it AFTER, e.g. } catch (InterruptedException e1) { try { mTracker.waitForID(id, 0); Thread.currentThread().interrupt(); // <— Here? } catch (InterruptedException e2) { loadStatus = MediaTracker.ABORTED; Thread.currentThread().interrupt(); } Thanks, Vlad Sent from myPad > On 28. Jan 2020, at 22:27, Jason Mehrens <jason_mehr...@hotmail.com> wrote: > > I see. Well I would have to do some more digging and testing to make myself > more knowledgeable on MediaTracker. > > Then the only bug in your current code is that you are not reasserting > interrupted status of the current thread in the case e1 is raised and e2 is > not. It is usually best to reassert the interrupted state at the end of the > method. > > Jason > > ________________________________________ > From: Volodin, Vladislav <vladislav.volo...@sap.com> > Sent: Tuesday, January 28, 2020 2:54 PM > To: Jason Mehrens > Cc: swing-dev@openjdk.java.net > Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage > > Hi Jason, > > I am not sure about the loop, because I don’t know if we can trust results > from mTracker.statusID at the moment when an exceptional case occurs. For > example, I was experimenting with the code and found out that the > MediaTracker can spawn a thread to load the image, or might use the current > thread, and the ABORTED state is never returned (I don’t even know how to > raise this state). That is why I don’t even know if your loop will ever stop. > > In my solution, I give the second chance only, and in case if the execution > was interrupted the second time, I explicitly assign the ABORTED state to > loadStatus. If the user wants to load this image once again, he can create > ImageIcon again (or even do this in a loop), or reinitialize it with a single > method (I don’t remember its name). > > What do you think? > > Kind regards, > Vlad > > Sent from myPad > >> On 28. Jan 2020, at 21:34, Jason Mehrens <jason_mehr...@hotmail.com> wrote: >> >> Vlad, >> >> I assume you would want to wait in a loop and reassert the interrupt at the >> end. >> >> === >> protected void loadImage(Image image) { >> MediaTracker mTracker = getTracker(); >> synchronized(mTracker) { >> int id = getNextID(); >> >> mTracker.addImage(image, id); >> boolean wasInterrupted = false; >> try { >> do { >> try { >> mTracker.waitForID(id, 0); >> } catch (InterruptedException e) { >> wasInterrupted = true; >> } >> loadStatus = mTracker.statusID(id, false); >> } while (loadStatus == MediaTracker.LOADING); >> mTracker.removeImage(image, id); >> >> width = image.getWidth(imageObserver); >> height = image.getHeight(imageObserver); >> } finally { >> if (wasInterrupted) { >> Thread.currentThread().interrupt(); >> } >> } >> } >> } >> === >> >> Jason >> ________________________________________ >> From: swing-dev <swing-dev-boun...@openjdk.java.net> on behalf of Volodin, >> Vladislav <vladislav.volo...@sap.com> >> Sent: Monday, January 27, 2020 11:11 AM >> To: Sergey Bylokhov >> Cc: swing-dev@openjdk.java.net >> Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage >> >> Hello Sergey, and others, >> >> here is the patch (made with "git diff") in the attachment. I have read that >> sometimes the attachments are lost. So here is my version with few comments >> regarding my code. I decided to use your approach with a small improvement. >> There is an excerpt of my patch. >> >> The idea is pretty simple: >> 1. I create an empty gif 1x1; >> 2. Initialize DefaultToolkit (I plan to interrupt the main thread, and if I >> do not initialize the toolkit in advance, my test will fail at the beginning >> 3. Interrupt the main thread >> 4. Try to load the icon: >> >> import javax.swing.*; >> import java.awt.*; >> >> public class imageIconInterrupted { >> static byte[] EMPTY_GIF = new byte[]{ >> (byte) 0x47, (byte) 0x49, (byte) 0x46, (byte) 0x38, (byte) 0x39, >> (byte) 0x61, (byte) 0x01, (byte) 0x00, >> (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, >> (byte) 0x21, (byte) 0xF9, (byte) 0x04, >> (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, >> (byte) 0x2C, (byte) 0x00, (byte) 0x00, >> (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, >> (byte) 0x00, (byte) 0x00, (byte) 0x02 >> }; >> >> public static void main(String[] args) throws Exception { >> Toolkit ignoreToolkit = Toolkit.getDefaultToolkit(); >> >> Thread.currentThread().interrupt(); >> ImageIcon iconInterrupt = new ImageIcon(EMPTY_GIF); >> if (iconInterrupt.getImageLoadStatus() != MediaTracker.COMPLETE) { >> throw new RuntimeException("Couldn't load GIF from bytes after >> interruption"); >> } >> } >> } >> >> The code of loadImage I have changed as follows: >> 1. I clear loadStatus for "finally" part; >> 2. Check the interruption according to your comments; >> 3. Change the status to ABORTED, if the interruption happened again (this >> part I cannot test, because I cannot properly interrupt the thread whenever >> I want. Multithreading is quite fragile there :( ) >> 4. update the status "interrupted" again; >> 5. and then - finally block. >> >> protected void loadImage(Image image) { >> ... >> try { >> loadStatus = 0; >> mTracker.addImage(image, id); >> mTracker.waitForID(id, 0); >> } catch (InterruptedException e1) { >> try { >> mTracker.waitForID(id, 0); >> } catch (InterruptedException e2) { >> loadStatus = MediaTracker.ABORTED; >> Thread.currentThread().interrupt(); >> } >> } finally { >> if (loadStatus == 0) { >> loadStatus = mTracker.statusID(id, false); >> } >> mTracker.removeImage(image, id); >> } >> >> P.S. if you think that my patch sounds fine, I will find a sponsor for the >> bug report and the patch preparation, so you can review it later. >> After the second attempt, my EMPTY_GIF was loaded successfully. The ABORTED >> part it seems that I don't know if it has ever worked. My patch (in the >> attachment) checks also the state ERROR for the URL that doesn't exist. >> Something like: >> >> ImageIcon iconNotExist = new ImageIcon(new >> URL("http://doesnt.exist.anywhere/1.gif")); // I am not sure if I spelled >> this URL grammatically correct >> if (iconNotExist.getImageLoadStatus() != MediaTracker.ERRORED) { >> throw new RuntimeException("Got unexpected status from >> non-existing GIF"); >> } >> >> Thanks to everyone. >> >> Kind regards, >> Vlad >> >> -----Original Message----- >> From: Sergey Bylokhov <sergey.bylok...@oracle.com> >> Sent: Dienstag, 21. Januar 2020 22:26 >> To: Volodin, Vladislav <vladislav.volo...@sap.com> >> Cc: Jason Mehrens <jason_mehr...@hotmail.com>; swing-dev@openjdk.java.net >> Subject: Re: <Swing Dev> Remove System.out.println from ImageIcon.loadImage >> >>>> On 1/21/20 1:14 pm, Volodin, Vladislav wrote: >>> Hi all, >>> >>> If I am not mistaken, this method is called from the constructor and other >>> methods. How long should we try loading the icon using the unmanaged (by >>> any thread pool, but I am not sure about this statement) thread? >>> >>> We don’t even have the flag “interrupted”. So technically this icon has to >>> be loaded. >> >> I think it is necessary to save the "interrupted" state in the catch >> block and try to call waitForID() again. It will be necessary to set >> "interrupted" flag for the Thread after that(when the waitForID will >> return without exception). >> >> >>> Sent from myFone >>> >>>>> On 21. Jan 2020, at 21:55, Sergey Bylokhov <sergey.bylok...@oracle.com> >>>>> wrote: >>>> >>>> On 1/21/20 12:26 pm, Jason Mehrens wrote: >>>>> +1 for Sergey suggestion. >>>> >>>> Or probably we need to try to load the image again because of the spec of >>>> the method state this: >>>> "Loads the image, returning only when the image is loaded." >>>> >>>>> ________________________________________ >>>>> From: Sergey Bylokhov <sergey.bylok...@oracle.com> >>>>> Sent: Sunday, January 19, 2020 9:31 PM >>>>> To: Volodin, Vladislav; Jason Mehrens >>>>> Cc: swing-dev@openjdk.java.net >>>>> Subject: Re: <Swing Dev> Remove System.out.println from >>>>> ImageIcon.loadImage >>>>> I guess there are no objections, probably the best way to fix >>>>> it is to drop the System.out.println and set interrupted flag. >>>>> On 1/16/20 7:05 am, Volodin, Vladislav wrote: >>>>>> If people in this distribution list agree, I can start working on a >>>>>> simple fix and either remove the logging (System.out.println), or >>>>>> replace it with PlatformLogger. I guess the second solution sounds >>>>>> better, but I don't know what is the better way to write a test-case for >>>>>> it. >>>>> -- >>>>> Best regards, Sergey. >>>> >>>> >>>> -- >>>> Best regards, Sergey. >> >> >> -- >> Best regards, Sergey.