tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Allen Reese <are...@yahoo-inc.com>
Subject RE: Cores with FlushableGzipOutputStream
Date Thu, 09 Feb 2012 20:07:15 GMT
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message