|
27 | 27 | import io.rsocket.DuplexConnection;
|
28 | 28 | import io.rsocket.Payload;
|
29 | 29 | import io.rsocket.RSocket;
|
30 |
| -import io.rsocket.frame.*; |
| 30 | +import io.rsocket.frame.CancelFrameCodec; |
| 31 | +import io.rsocket.frame.ErrorFrameCodec; |
| 32 | +import io.rsocket.frame.FrameHeaderCodec; |
| 33 | +import io.rsocket.frame.FrameType; |
| 34 | +import io.rsocket.frame.PayloadFrameCodec; |
| 35 | +import io.rsocket.frame.RequestChannelFrameCodec; |
| 36 | +import io.rsocket.frame.RequestNFrameCodec; |
| 37 | +import io.rsocket.frame.RequestStreamFrameCodec; |
31 | 38 | import io.rsocket.frame.decoder.PayloadDecoder;
|
32 | 39 | import io.rsocket.internal.SynchronizedIntObjectHashMap;
|
33 | 40 | import io.rsocket.internal.UnboundedProcessor;
|
|
46 | 53 | import org.slf4j.LoggerFactory;
|
47 | 54 | import reactor.core.Disposable;
|
48 | 55 | import reactor.core.Exceptions;
|
49 |
| -import reactor.core.publisher.*; |
| 56 | +import reactor.core.publisher.BaseSubscriber; |
| 57 | +import reactor.core.publisher.Flux; |
| 58 | +import reactor.core.publisher.Mono; |
| 59 | +import reactor.core.publisher.SignalType; |
| 60 | +import reactor.core.publisher.UnicastProcessor; |
50 | 61 | import reactor.util.annotation.Nullable;
|
51 | 62 | import reactor.util.concurrent.Queues;
|
52 | 63 |
|
@@ -129,19 +140,7 @@ class RSocketResponder implements RSocket {
|
129 | 140 |
|
130 | 141 | private void handleSendProcessorError(Throwable t) {
|
131 | 142 | cleanUpSendingSubscriptions();
|
132 |
| - |
133 |
| - channelProcessors |
134 |
| - .values() |
135 |
| - .forEach( |
136 |
| - subscription -> { |
137 |
| - try { |
138 |
| - subscription.onError(t); |
139 |
| - } catch (Throwable e) { |
140 |
| - if (LOGGER.isDebugEnabled()) { |
141 |
| - LOGGER.debug("Dropped exception", t); |
142 |
| - } |
143 |
| - } |
144 |
| - }); |
| 143 | + cleanUpChannelProcessors(t); |
145 | 144 | }
|
146 | 145 |
|
147 | 146 | private void tryTerminateOnConnectionError(Throwable e) {
|
@@ -278,16 +277,15 @@ private synchronized void cleanUpSendingSubscriptions() {
|
278 | 277 | }
|
279 | 278 |
|
280 | 279 | private synchronized void cleanUpChannelProcessors(Throwable e) {
|
281 |
| - channelProcessors |
282 |
| - .values() |
283 |
| - .forEach( |
284 |
| - payloadPayloadProcessor -> { |
285 |
| - try { |
286 |
| - payloadPayloadProcessor.onError(e); |
287 |
| - } catch (Throwable t) { |
288 |
| - // noops |
289 |
| - } |
290 |
| - }); |
| 280 | + // Iterate explicitly to handle collisions with concurrent removals |
| 281 | + for (IntObjectMap.PrimitiveEntry<Processor<Payload, Payload>> entry : |
| 282 | + channelProcessors.entries()) { |
| 283 | + try { |
| 284 | + entry.value().onError(e); |
| 285 | + } catch (Throwable ex) { |
| 286 | + // noops |
| 287 | + } |
| 288 | + } |
291 | 289 | channelProcessors.clear();
|
292 | 290 | }
|
293 | 291 |
|
|
0 commit comments