|
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