unsubscribe
> From: are...@yahoo-inc.com > To: users@tomcat.apache.org > CC: laraa...@yahoo-inc.com > Date: Thu, 9 Feb 2012 12:07:15 -0800 > Subject: RE: Cores with FlushableGzipOutputStream > > Try again now that I'm subscribed. > > > > -----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 >