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
*/
}
}
}