I'll have to get Simes to look into the detection route - I don't recall any such thing as an isClosed() method on an InputStream though. I could be wrong. I know in our own code, we have this exact same try/catch approach for a case where a library was sometimes closing a stream.

No particular issue on the logging idea - except those logs will be quite noisy at times. We get the exception on pretty much every bundle load over a slow remote connection e.g. cloud machines being used for remote deployment.

-- Rob


On 18/09/2014 15:52, Richard S. Hall wrote:
On 9/18/14 09:08 , Rob Walker wrote:
Well, correct behaviour would be to not close the stream multiple times. Personally, I think it's bad form for a block of code to issue a close() on a stream that it didn't open, it's not symmetrical. But that's not always as easy to avoid as it sounds. In this case, completely avoiding a double close may not be possible since there is a suspicion at least one of the close calls is happening inside Jetty. At least that is my understanding, I wasn't the one who found the original issue.

The problem with not ignoring the close exception, is that without that try {} catch block the duplicate close causes a fatal exception which prevents HTTP based bundle loading from working. The only exceptions we've ever trapped inside this block is the duplicate close - of course others with different topologies may be able to trigger other close() exceptions.

For us, we see the double close happening regularly when our server is significantly remote from teh instance we are web starting e.g. the Felix based code server is in our office, and the instance being launched over Web Start is on an AWS cloud server. In this setup, we get regular launch failures which prevent the application launching. So ignoring the duplicate close is definitely the lesser of two evils!

So, I'm guessing there is no way to detect the double close situation?

In the end, it probably doesn't make that much of a difference, but perhaps if we cannot detect the case we are trying to ignore, then we should at least log these situations rather than ignore them completely.

-> richard

/
//For Raymond: stack trace attached/

/We're on a pretty old version of Jetty (6.1.26 I think). We have a task to update this at some stage, but when it works fine you tend to leave it. Note that the JarRevision code hasn't changed as far as I can see, so if Jetty behaviour is different in this area I suspect the problem will still be lurking even in newer versions//
/
-- Rob


On 18/09/2014 14:35, Richard S. Hall wrote:
I guess the question to ask is what behavior is the correct behavior if there really is an exception on close? This patch will ignore every exception, not just ones that occurs because of a double close (although it seems to me a double close should be a no-op, not sure why it throws, but that is another issue).

Does it make sense that every close exception is ignored and the user is never alerted? Granted, there isn't much we can do, but often such errors are better breaking things than just being ignored.

-> richard

On 9/18/14 03:43 , Rob Walker wrote:
Just wanted to check this one before I raise a JIRA, in case it's known and/or already been fixed or being worked on.

In one of our models we provision our application over WebStart, which causes bundles to be loaded over HTTP. Occasionally we get a Stream Closed exception being thrown from the Jetty HTTP server (the server serving up the code is also running under Felix).

What seems to happen is a double close of the input stream - which throws an error. I've include the notes below from our developer who found this.

It's a pretty simple mod to ignore the exception on second close (highlighted red below) - assuming everyone is happy this is an ok approach.

-- Rob

===

/It turns out the problem was arising when caching the VersaTest jar files. Whilst they are coming across via WebStart ok, an error was being thrown because the stream used to read them was being closed multiple times and at some point the close operation causes an exception that isn't caught so stops the load. This error occurs in Felix in the JarRevision class, in the initialize() method. I put a simple fix in that ignored the error on close. So in the code below, a close on the input stream was being called in the //BundleCache.copyStreamToFile(is, m_bundleFile) and in the bottom finally block (you can see below where I put in that disregarding catch. (Note, I suspect that also the input stream could be closed in the //((HttpURLConnection) conn).disconnect() //as well. But it is explicitly closed in the copyStreamToFile.)////
///

                if (!byReference)
                {
                    URLConnection conn = null;
                    try
                    {
                        if (is == null)
                        {
// Do it the manual way to have a chance to // set request properties such as proxy auth. URL url = BundleCache.getSecureAction().createURL(
                                null, getLocation(), null);
                            conn = url.openConnection();

                            // Support for http proxy authentication.
String auth = BundleCache.getSecureAction()
.getSystemProperty("http.proxyAuth", null);
                            if ((auth != null) && (auth.length() > 0))
                            {
if ("http".equals(url.getProtocol()) ||
"https".equals(url.getProtocol()))
                                {
String base64 = Util.base64Encode(auth);
conn.setRequestProperty(
"Proxy-Authorization", "Basic " + base64);
                                }
                            }
                            is = BundleCache.getSecureAction()
.getURLConnectionInputStream(conn);
                        }

                        // Save the bundle jar file.
BundleCache.copyStreamToFile(is, m_bundleFile);
                    }
                    finally
                    {
// This is a hack to fix an issue on Android, where // HttpURLConnections are not properly closed. (FELIX-2728) if ((conn != null) && (conn instanceof HttpURLConnection))
                        {
                            ((HttpURLConnection) conn).disconnect();
                        }
                    }
                }
            }
        }
        finally
        {
            if (is != null)
            {
                try
                {
                    is.close();
                } catch (IOException ioe)
                {
/* Catch and disregard exception on close as could already have been closed, either in the disconnect or in the copyStreamToProfile
                    */

                }

            }
        }













--


Ascert - Taking systems to the edge
r...@ascert.com
SA +27 21 300 2028
UK +44 20 7488 3470 ext 5119
www.ascert.com



--


Ascert - Taking systems to the edge
r...@ascert.com
SA +27 21 300 2028
UK +44 20 7488 3470 ext 5119
www.ascert.com

Reply via email to