Skip to content

Commit b1c19c0

Browse files
Merge pull request #8134 from eclipse/jetty-10.0.x-websocketPermessageDeflatePools
Improve cleanup of deflater/inflater pools for PerMessageDeflateExtension
2 parents 23948f1 + 3901159 commit b1c19c0

File tree

8 files changed

+309
-11
lines changed

8 files changed

+309
-11
lines changed

jetty-util/src/main/java/org/eclipse/jetty/util/compression/CompressionPool.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@
1616
import java.io.Closeable;
1717

1818
import org.eclipse.jetty.util.Pool;
19-
import org.eclipse.jetty.util.component.AbstractLifeCycle;
19+
import org.eclipse.jetty.util.annotation.ManagedObject;
20+
import org.eclipse.jetty.util.component.ContainerLifeCycle;
2021

21-
public abstract class CompressionPool<T> extends AbstractLifeCycle
22+
@ManagedObject
23+
public abstract class CompressionPool<T> extends ContainerLifeCycle
2224
{
2325
public static final int DEFAULT_CAPACITY = 1024;
2426

@@ -51,6 +53,11 @@ public void setCapacity(int capacity)
5153
_capacity = capacity;
5254
}
5355

56+
public Pool<Entry> getPool()
57+
{
58+
return _pool;
59+
}
60+
5461
protected abstract T newPooled();
5562

5663
protected abstract void end(T object);
@@ -85,7 +92,10 @@ public void release(Entry entry)
8592
protected void doStart() throws Exception
8693
{
8794
if (_capacity > 0)
95+
{
8896
_pool = new Pool<>(Pool.StrategyType.RANDOM, _capacity, true);
97+
addBean(_pool);
98+
}
8999
super.doStart();
90100
}
91101

@@ -95,6 +105,7 @@ public void doStop() throws Exception
95105
if (_pool != null)
96106
{
97107
_pool.close();
108+
removeBean(_pool);
98109
_pool = null;
99110
}
100111
super.doStop();

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/Extension.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,25 @@
1313

1414
package org.eclipse.jetty.websocket.core;
1515

16+
import java.io.Closeable;
17+
1618
/**
1719
* Interface for WebSocket Extensions.
1820
* <p>
1921
* That {@link Frame}s are passed through the Extension via the {@link IncomingFrames} and {@link OutgoingFrames} interfaces
2022
*/
21-
public interface Extension extends IncomingFrames, OutgoingFrames
23+
public interface Extension extends IncomingFrames, OutgoingFrames, Closeable
2224
{
2325

2426
void init(ExtensionConfig config, WebSocketComponents components);
2527

28+
/**
29+
* Used to clean up any resources after connection close.
30+
*/
31+
default void close()
32+
{
33+
}
34+
2635
/**
2736
* The active configuration for this extension.
2837
*

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/internal/ExtensionStack.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,22 @@ public ExtensionStack(WebSocketComponents components, Behavior behavior)
6060
this.behavior = behavior;
6161
}
6262

63+
public void close()
64+
{
65+
for (Extension ext : extensions)
66+
{
67+
try
68+
{
69+
ext.close();
70+
}
71+
catch (Throwable t)
72+
{
73+
if (LOG.isDebugEnabled())
74+
LOG.debug("Extension Error During Close", t);
75+
}
76+
}
77+
}
78+
6379
@ManagedAttribute(name = "Extension List", readonly = true)
6480
public List<Extension> getExtensions()
6581
{

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/internal/FrameFlusher.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ public class FrameFlusher extends IteratingCallback
4444
{
4545
public static final Frame FLUSH_FRAME = new Frame(OpCode.BINARY);
4646
private static final Logger LOG = LoggerFactory.getLogger(FrameFlusher.class);
47-
private static final Throwable CLOSED_CHANNEL = new ClosedChannelException();
4847

4948
private final AutoLock lock = new AutoLock();
5049
private final LongAdder messagesOut = new LongAdder();
@@ -185,7 +184,15 @@ public void onClose(Throwable cause)
185184
{
186185
try (AutoLock l = lock.lock())
187186
{
188-
closedCause = cause == null ? CLOSED_CHANNEL : cause;
187+
// TODO: find a way to not create exception if cause is null.
188+
closedCause = cause == null ? new ClosedChannelException()
189+
{
190+
@Override
191+
public Throwable fillInStackTrace()
192+
{
193+
return this;
194+
}
195+
} : cause;
189196
}
190197
iterate();
191198
}

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/internal/PerMessageDeflateExtension.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
package org.eclipse.jetty.websocket.core.internal;
1515

1616
import java.nio.ByteBuffer;
17+
import java.nio.channels.ClosedChannelException;
1718
import java.util.HashMap;
1819
import java.util.Map;
1920
import java.util.concurrent.atomic.AtomicReference;
@@ -146,6 +147,24 @@ public void init(final ExtensionConfig config, WebSocketComponents components)
146147
super.init(configNegotiated, components);
147148
}
148149

150+
@Override
151+
public void close()
152+
{
153+
// TODO: use IteratingCallback.close() instead of creating exception with failFlusher methods.
154+
ClosedChannelException exception = new ClosedChannelException()
155+
{
156+
@Override
157+
public Throwable fillInStackTrace()
158+
{
159+
return this;
160+
}
161+
};
162+
incomingFlusher.failFlusher(exception);
163+
outgoingFlusher.failFlusher(exception);
164+
releaseInflater();
165+
releaseDeflater();
166+
}
167+
149168
private static String toDetail(Inflater inflater)
150169
{
151170
return String.format("Inflater[finished=%b,read=%d,written=%d,remaining=%d,in=%d,out=%d]", inflater.finished(), inflater.getBytesRead(),

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/internal/TransformingFlusher.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,34 @@ public final void sendFrame(Frame frame, Callback callback, boolean batch)
7777
notifyCallbackFailure(callback, failure);
7878
}
7979

80+
/**
81+
* Used to fail this flusher possibly from an external event such as a callback.
82+
* @param t the failure.
83+
*/
84+
public void failFlusher(Throwable t)
85+
{
86+
// TODO: find a way to close the flusher in non error case without exception.
87+
boolean failed = false;
88+
try (AutoLock l = lock.lock())
89+
{
90+
if (failure == null)
91+
{
92+
failure = t;
93+
failed = true;
94+
}
95+
else
96+
{
97+
failure.addSuppressed(t);
98+
}
99+
}
100+
101+
if (failed)
102+
{
103+
flusher.failed(t);
104+
flusher.iterate();
105+
}
106+
}
107+
80108
private void onFailure(Throwable t)
81109
{
82110
try (AutoLock l = lock.lock())
@@ -103,8 +131,14 @@ private class Flusher extends IteratingCallback implements Callback
103131
private FrameEntry current;
104132

105133
@Override
106-
protected Action process()
134+
protected Action process() throws Throwable
107135
{
136+
try (AutoLock l = lock.lock())
137+
{
138+
if (failure != null)
139+
throw failure;
140+
}
141+
108142
if (finished)
109143
{
110144
if (current != null)
@@ -134,8 +168,11 @@ protected void onCompleteFailure(Throwable t)
134168
if (log.isDebugEnabled())
135169
log.debug("onCompleteFailure {}", t.toString());
136170

137-
notifyCallbackFailure(current.callback, t);
138-
current = null;
171+
if (current != null)
172+
{
173+
notifyCallbackFailure(current.callback, t);
174+
current = null;
175+
}
139176
onFailure(t);
140177
}
141178
}

jetty-websocket/websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/internal/WebSocketCoreSession.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,12 +254,13 @@ public void onEof()
254254
closeConnection(sessionState.getCloseStatus(), Callback.NOOP);
255255
}
256256

257-
public void closeConnection(CloseStatus closeStatus, Callback callback)
257+
private void closeConnection(CloseStatus closeStatus, Callback callback)
258258
{
259259
if (LOG.isDebugEnabled())
260260
LOG.debug("closeConnection() {} {}", closeStatus, this);
261261

262262
abort();
263+
extensionStack.close();
263264

264265
// Forward Errors to Local WebSocket EndPoint
265266
if (closeStatus.isAbnormal() && closeStatus.getCause() != null)

0 commit comments

Comments
 (0)