supabase / supabase-flutter

Flutter integration for Supabase. This package makes it simple for developers to build secure and scalable products.
https://supabase.com/
MIT License
662 stars 155 forks source link

Realtime_client: Concurrent modification during iteration of a GrowableList #833

Open seadynamic8 opened 4 months ago

seadynamic8 commented 4 months ago

Describe the bug I get multiple errors from Sentry logs. No local debug errors.

ConcurrentModificationError: Concurrent modification during iteration: Instance(length:11) of '_GrowableList'.
  File "iterable.dart", line 348, col 7, in ListIterator.moveNext
  File "iterable.dart", line 450, col 22, in WhereIterator.moveNext
  File "iterable.dart", line 347, col 23, in Iterable.forEach
  File "realtime_client.dart", line 336, col 12, in RealtimeClient.onConnMessage.<fn>
  File "realtime_client.dart", line 140, col 21, in new RealtimeClient.<fn>
  File "realtime_client.dart", line 319, col 11, in RealtimeClient.onConnMessage
  File "realtime_client.dart", line 170, col 22, in RealtimeClient.connect.<fn>
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_pipe.dart", line 123, col 11, in _ForwardingStreamSubscription._add
  File "stream_pipe.dart", line 253, col 10, in _HandleErrorStream._handleData
  File "stream_pipe.dart", line 153, col 13, in _ForwardingStreamSubscription._handleData
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_controller.dart", line 784, col 19, in _SyncStreamControllerDispatch._sendData
  File "stream_controller.dart", line 658, col 7, in _StreamController._add
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_controller.dart", line 784, col 19, in _SyncStreamControllerDispatch._sendData
  File "stream_controller.dart", line 658, col 7, in _StreamController._add
  File "stream_controller.dart", line 606, col 5, in _StreamController.add
  File "websocket_impl.dart", line 1144, col 21, in new _WebSocketImpl._fromSocket.<fn>
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_transformers.dart", line 63, col 11, in _SinkTransformerStreamSubscription._add
  File "stream_transformers.dart", line 13, col 11, in _EventSinkWrapper.add
  File "websocket_impl.dart", line 332, col 23, in _WebSocketProtocolTransformer._messageFrameEnd
  File "websocket_impl.dart", line 226, col 46, in _WebSocketProtocolTransformer.add
  File "stream_transformers.dart", line 111, col 24, in _SinkTransformerStreamSubscription._handleData
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_controller.dart", line 784, col 19, in _SyncStreamControllerDispatch._sendData
  File "stream_controller.dart", line 658, col 7, in _StreamController._add
  File "stream_controller.dart", line 606, col 5, in _StreamController.add
  File "socket_patch.dart", line 2447, col 41, in _Socket._onData
  File "zone.dart", line 1594, col 10, in _RootZone.runUnaryGuarded
  File "stream_impl.dart", line 339, col 11, in _BufferingStreamSubscription._sendData
  File "stream_impl.dart", line 271, col 7, in _BufferingStreamSubscription._add
  File "stream_controller.dart", line 784, col 19, in _SyncStreamControllerDispatch._sendData
  File "stream_controller.dart", line 658, col 7, in _StreamController._add
  File "stream_controller.dart", line 606, col 5, in _StreamController.add
  File "socket_patch.dart", line 1936, col 33, in new _RawSocket.<fn>
  File "socket_patch.dart", line 1379, col 14, in _NativeSocket.issueReadEvent.issue
  File "schedule_microtask.dart", line 40, col 21, in _microtaskLoop
  File "schedule_microtask.dart", line 49, col 5, in _startMicrotaskLoop

It happens in the realtime_client code.

Something similar happened in the Flutter codebase: https://github.com/flutter/flutter/issues/131415

I think it has to do with not making a copy of the list of callbacks before calling them in the list:

// Possibly here (bad)

Line 341:
for (final callback in stateChangeCallbacks['message']!) {
        callback(msg);
      }

// Possible fix (good)

for (final callback in List.of(stateChangeCallbacks['message']!)) {
        callback(msg);
      }

To Reproduce i am not sure which code is causing it from my end since the stacktrace shows only the library code.

Expected behavior Either propagate the error to client code or needs a code fix.

Version (please complete the following information): ├── supabase_flutter 1.10.25 │ ├── supabase 1.11.11 │ │ ├── functions_client 1.3.2 │ │ ├── gotrue 1.12.6 │ │ ├── postgrest 1.5.2 │ │ ├── realtime_client 1.4.0 │ │ ├── storage_client 1.5.4

Additional context The growable list size changes but basically the same error each time.

seadynamic8 commented 4 months ago

Updated to supabase v2, still occuring. (The code referenced above doesn't seemed to have changed)

├── supabase_flutter 2.3.3 │ ├── supabase 2.0.7 │ │ ├── functions_client 2.0.0 │ │ ├── gotrue 2.5.0 │ │ ├── postgrest 2.1.0 │ │ ├── realtime_client 2.0.0 │ │ ├── storage_client 2.0.1

Vinzent03 commented 3 months ago

Do you still encounter this issue? I guess you're somewhere calling realtimeclient.onMessage() inside a callback passed to onMessage().