mongo-dart / mongo_dart

Mongo_dart: MongoDB driver for Dart programming language
https://pub.dev/packages/mongo_dart
MIT License
445 stars 98 forks source link

Stack overflow when reading data #127

Open timk10 opened 6 years ago

timk10 commented 6 years ago

We run into stack overflow error due to handleBody/handleHeader calling itself repeatedly (see stacktrace)

`Socket error Stack Overflow

0 List.setRange (dart:core-patch/array.dart:31)

1 PacketConverter._readPacketIntoBuffer (package:plato_mongo_dart/src/network/packet_converter.dart:72:12)

2 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:63:19)

3 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

4 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:48:7)

5 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

6 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:48:7)

7 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

8 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:48:7)

9 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

10 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:48:7)

11 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

12 PacketConverter.handleBody (package:plato_mongo_dart/src/network/packet_converter.dart:48:7)

13 PacketConverter.handleHeader (package:plato_mongo_dart/src/network/packet_converter.dart:37:7)

... ...

14864 _StreamController.add (dart:async/stream_controller.dart:603)

14865 _Socket._onData (dart:io-patch/socket_patch.dart:1617)

14866 StackZoneSpecification._registerUnaryCallback.. (package:stack_trace/src/stack_zone_specification.dart)

14867 StackZoneSpecification._run (package:stack_trace/src/stack_zone_specification.dart)

14868 StackZoneSpecification._registerUnaryCallback. (package:stack_trace/src/stack_zone_specification.dart:107:14)

14869 _rootRunUnary (dart:async/zone.dart)

14870 _CustomZone.runUnaryGuarded (dart:async/zone.dart)

14871 _StreamController.add (dart:async/stream_controller.dart:603)

14872 new _RawSocket. (dart:io-patch/socket_patch.dart:1203)

14873 _NativeSocket.issueReadEvent.issue (dart:io-patch/socket_patch.dart)

14874 _startMicrotaskLoop (dart:async/schedule_microtask.dart)

14875 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart)`

Upon reading the code it seems if there are more than 7400+ messages in a single packet (back of napkin calculation: based on the # of stacks, around 14864/2 ~ 7432 messages) then it would cause the 2 functions calling each other until stack overflow.

Seems there could be 2 scenarios

  1. If Mongo decides to send a packet with many messages.
  2. It's also possible that Dart batches all the messages into a single packet.

I'm not able to reproduce it locally, but I do see it happen quite often in production so I'm not able to nail down which of the above scenarios caused the issue.

Is there a reason why we choose to read the packets recursively? Should we handle reading of the packets in iterative manner rather than recursive?

Pacane commented 6 years ago

Sorry, is this really a mongo_dart issue? I don't see any line in the stacktrace that belongs to mongo_dart?

timk10 commented 6 years ago

Sorry, we forked a version of it so that we could reconnect if there were socket error Change is here: (https://github.com/timk10/mongo_dart/commit/9070d7e7823b19f3135443eea54e285647a2efe7).

However rest of the code is still the same.