grpc-dart
grpc-dart copied to clipboard
Fix hang that occurs when streaming calls are ongoing and a hot-restart occurs in Flutter web
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.