grpc-dart icon indicating copy to clipboard operation
grpc-dart copied to clipboard

Fix hang that occurs when streaming calls are ongoing and a hot-restart occurs in Flutter web

Open galenwarren opened this issue 8 months ago • 23 comments

When hot-restarting in Flutter Web, streaming GRPC calls can get stuck in this method of _GrpcWebConversionSink:

  @override
  void add(ByteBuffer chunk) {
    _chunkOffset = 0;
    final chunkData = chunk.asUint8List();
    while (_chunkOffset < chunk.lengthInBytes) {
      switch (_state) {
        case _GrpcWebParseState.init:
          _frameType = _parseFrameType(chunkData);
          break;
        case _GrpcWebParseState.length:
          _parseLength(chunkData);
          break;
        case _GrpcWebParseState.message:
          _parseMessage(chunkData);
          break;
      }
    }
    _chunkOffset = 0;
  }

The while loop runs, but the switch statement doesn't match any cases so it just keeps looping. This seems to have something to with some issues around how Dart handles enums across isolates (some discussion here and elsewhere) and the fact that hot-restarting involves the creation of a new isolate.

In any case, adding a default handler causes the loop to break when a call is orphaned in this manner, which lets the isolate shut down and the hot-restart succeed.

There is also some discussion in the Dart/Flutter community about creating hooks for all platforms that would allow one to reliably detect when an isolate were shutting down and take action. If that were in place, that would allow for a cleaner solution, but it doesn't seem to be available yet.

galenwarren avatar Jun 23 '24 18:06 galenwarren