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