On 09/02/2012 20:07, Allen Reese wrote: > Try again now that I'm subscribed.
If libzip.so is provided by the JVM installer (and I think it is) then it is still a JVM problem. See [1] for an example where Oracle did accept that an crash in libzip.so was a bug. All changing the Tomcat code indicates is that some paths trigger the bug and some don't. That does not absolve the JVM of responsibility. Mark [1] http://bugs.sun.com/view_bug.do?bug_id=6866479 > > >> -----Original Message----- >> From: Allen Reese >> Sent: Thursday, February 09, 2012 12:03 PM >> To: 'users@tomcat.apache.org' >> Cc: Lars Anderson >> Subject: Cores with FlushableGzipOutputStream >> >> We've just upgraded from tomcat 6.0.33 to 6.0.35 and started having the >> JVM core on our production boxes. >> >> I'm trying to determine what the next course of action should be here. >> I have an Oracle Support contract, but they don't seem to see this as a >> JVM issue, and blame it on a native lib. >> >> >> Thanks. >> >> Allen Reese >> Core Platforms >> Yahoo!, Inc. >> >> Running on linux x86-64, jdk 6u27, 6u29, 6u30, 7u2 >> >> We run several tests and the output is: >> >> Jdk | Version | flags >> | >> 6u30 | 6.0.33 | compression enabled >> | works >> 6u30 | 6.0.35 | compression enabled >> | cores >> 6u30 | 6.0.35 | compression disabled >> | works >> 6u30 | 6.0.35 | Remove changes to FlushableGzipOutputStream [1] >> | works >> 6u30 | 6.0.35 | -Dsun.zip.disableMemoryMapping=true >> | cores >> >> 7u2 | 6.0.35 | compression enabled >> | cores >> 7u2 | 6.0.35 | compression disabled >> | >> 7u2 | 6.0.35 | Remove changes to FlushableGzipOutputStream [1] >> | >> 7u2 | 6.0.35 | -Dsun.zip.disableMemoryMapping=true >> | cores >> >> https://issues.apache.org/bugzilla/show_bug.cgi?id=52121 >> >> I filed an SR with Oracle, as this looks like a JVM bug and got the >> following response: >> >> Generic Note >> ------------------------ >> Hi Allen, >> >> Thank you for sending the hotspot error logs (hs_err_pid<pid>). Each >> one of them has verbiage that indicates the problem is not with Java, >> but with native code: >> >> # Problematic frame: >> # C [libzip.so+0x77e3] char+0xa3 >> # >> # If you would like to submit a bug report, please visit: >> # http://java.sun.com/webapps/bugreport/crash.jsp >> # The crash happened outside the Java Virtual Machine in native code. >> # See problematic frame for where to report the bug. >> # >> >> The case description also noted: >> >> Rolling back this patch to tomcat increases stability: >> http://svn.apache.org/viewvc?view=revision&revision=1197382 >> >> Again, this points to software other than Java. The Java defect >> mentioned, 4813885, was fixed in June of 2009. >> ===================== >> >> Allen Reese >> Core Platforms >> Yahoo!, Inc. >> >> [1]: Patch to remove changes to FlushableGZIPOutputStream from 6.0.35. >> >> --- apache-tomcat-6.0.35- >> src/java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.jav >> a 2011-11-28 02:22:45.000000000 -0800 >> +++ apache-tomcat-6.0.33- >> src/java/org/apache/coyote/http11/filters/FlushableGZIPOutputStream.jav >> a 2011-08-16 05:26:14.000000000 -0700 >> @@ -35,93 +35,58 @@ >> super(os); >> } >> >> + private static final byte[] EMPTYBYTEARRAY = new byte[0]; >> + private boolean hasData = false; >> + >> /** >> - * It is used to reserve one byte of real data so that it can be >> used when >> - * flushing the stream. >> + * Here we make sure we have received data, so that the header has >> been for >> + * sure written to the output stream already. >> */ >> - private byte[] lastByte = new byte[1]; >> - private boolean hasLastByte = false; >> - >> - @Override >> - public void write(byte[] bytes) throws IOException { >> - write(bytes, 0, bytes.length); >> - } >> - >> @Override >> - public synchronized void write(byte[] bytes, int offset, int >> length) >> + public synchronized void write(byte[] bytes, int i, int i1) >> throws IOException { >> - if (length > 0) { >> - flushLastByte(); >> - if (length > 1) { >> - super.write(bytes, offset, length - 1); >> - } >> - rememberLastByte(bytes[offset + length - 1]); >> - } >> + super.write(bytes, i, i1); >> + hasData = true; >> } >> >> @Override >> public synchronized void write(int i) throws IOException { >> - flushLastByte(); >> - rememberLastByte((byte) i); >> + super.write(i); >> + hasData = true; >> } >> >> @Override >> - public synchronized void finish() throws IOException { >> - try { >> - flushLastByte(); >> - } catch (IOException ignore) { >> - // If our write failed, then trailer write in finish() >> will fail >> - // with IOException as well, but it will leave Deflater in >> more >> - // consistent state. >> - } >> - super.finish(); >> + public synchronized void write(byte[] bytes) throws IOException { >> + super.write(bytes); >> + hasData = true; >> } >> >> @Override >> - public synchronized void close() throws IOException { >> - try { >> - flushLastByte(); >> - } catch (IOException ignored) { >> - // Ignore. As OutputStream#close() says, the contract of >> close() >> - // is to close the stream. It does not matter much if the >> - // stream is not writable any more. >> + public synchronized void flush() throws IOException { >> + if (!hasData) { >> + return; // do not allow the gzip header to be flushed on >> its own >> } >> - super.close(); >> - } >> >> - private void rememberLastByte(byte b) { >> - lastByte[0] = b; >> - hasLastByte = true; >> - } >> + // trick the deflater to flush >> + /** >> + * Now this is tricky: We force the Deflater to flush its data >> by >> + * switching compression level. As yet, a perplexingly simple >> workaround >> + * for >> + * >> http://developer.java.sun.com/developer/bugParade/bugs/4255743.html >> + */ >> + if (!def.finished()) { >> + def.setInput(EMPTYBYTEARRAY, 0, 0); >> >> - private void flushLastByte() throws IOException { >> - if (hasLastByte) { >> - // Clear the flag first, because write() may fail >> - hasLastByte = false; >> - super.write(lastByte, 0, 1); >> - } >> - } >> + def.setLevel(Deflater.NO_COMPRESSION); >> + deflate(); >> >> - @Override >> - public synchronized void flush() throws IOException { >> - if (hasLastByte) { >> - // - do not allow the gzip header to be flushed on its own >> - // - do not do anything if there is no data to send >> - >> - // trick the deflater to flush >> - /** >> - * Now this is tricky: We force the Deflater to flush its >> data by >> - * switching compression level. As yet, a perplexingly >> simple workaround >> - * for >> - * >> http://developer.java.sun.com/developer/bugParade/bugs/4255743.html >> - */ >> - if (!def.finished()) { >> - def.setLevel(Deflater.NO_COMPRESSION); >> - flushLastByte(); >> - def.setLevel(Deflater.DEFAULT_COMPRESSION); >> - } >> + def.setLevel(Deflater.DEFAULT_COMPRESSION); >> + deflate(); >> + >> + out.flush(); >> } >> - out.flush(); >> + >> + hasData = false; // no more data to flush >> } >> >> /* > > --------------------------------------------------------------------- > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org