424847 - Deadlock in deflate-frame (webkit binary)

+ Moving notification flows to outside of the synchronization blocks
This commit is contained in:
Joakim Erdfelt 2014-01-07 11:14:28 -07:00
parent 8720fb213c
commit f0eeb27921
1 changed files with 81 additions and 63 deletions

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.websocket.common.extensions.compress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
@ -45,8 +47,7 @@ public class DeflateFrameExtension extends AbstractExtension
private static final int OVERHEAD = 64;
/** Tail Bytes per Spec */
private static final byte[] TAIL = new byte[]
{ 0x00, 0x00, (byte)0xFF, (byte)0xFF };
private static final byte[] TAIL = new byte[] { 0x00, 0x00, (byte)0xFF, (byte)0xFF };
private int bufferSize = 64 * 1024;
private Deflater compressor;
private Inflater decompressor;
@ -58,7 +59,7 @@ public class DeflateFrameExtension extends AbstractExtension
}
@Override
public synchronized void incomingFrame(Frame frame)
public void incomingFrame(Frame frame)
{
if (OpCode.isControlFrame(frame.getOpCode()) || !frame.isRsv1())
{
@ -80,7 +81,6 @@ public class DeflateFrameExtension extends AbstractExtension
byte compressed[] = new byte[inlen + TAIL.length];
payload.get(compressed,0,inlen);
System.arraycopy(TAIL,0,compressed,inlen,TAIL.length);
decompressor.setInput(compressed,0,compressed.length);
// Since we don't track text vs binary vs continuation state, just grab whatever is the greater value.
int maxSize = Math.max(getPolicy().getMaxTextMessageSize(),getPolicy().getMaxBinaryMessageBufferSize());
@ -89,6 +89,10 @@ public class DeflateFrameExtension extends AbstractExtension
DataFrame out = new DataFrame(frame);
out.setRsv1(false); // Unset RSV1
synchronized (decompressor)
{
decompressor.setInput(compressed,0,compressed.length);
// Perform decompression
while (decompressor.getRemaining() > 0 && !decompressor.finished())
{
@ -118,6 +122,7 @@ public class DeflateFrameExtension extends AbstractExtension
throw new BadPayloadException(e);
}
}
}
// Forward on the frame
out.setPayload(accumulator.getByteBuffer(getBufferPool()));
@ -136,7 +141,7 @@ public class DeflateFrameExtension extends AbstractExtension
}
@Override
public synchronized void outgoingFrame(Frame frame, WriteCallback callback)
public void outgoingFrame(Frame frame, WriteCallback callback)
{
if (OpCode.isControlFrame(frame.getOpCode()))
{
@ -160,7 +165,10 @@ public class DeflateFrameExtension extends AbstractExtension
// Prime the compressor
byte uncompressed[] = BufferUtil.toArray(frame.getPayload());
List<DataFrame> dframes = new ArrayList<>();
synchronized (compressor)
{
// Perform the compression
if (!compressor.finished())
{
@ -205,13 +213,23 @@ public class DeflateFrameExtension extends AbstractExtension
{
// this is fragmented
out.setFin(false);
nextOutgoingFrame(out,null); // non final frames have no callback
}
dframes.add(out);
}
}
}
// notify outside of synchronize
for (DataFrame df : dframes)
{
if (df.isFin())
{
nextOutgoingFrame(df,callback);
}
else
{
// pass through the callback
nextOutgoingFrame(out,callback);
}
// non final frames have no callback
nextOutgoingFrame(df,null);
}
}
}