Skip to content

Commit

Permalink
Protect from identityHashCode equal to 0. (#90)
Browse files Browse the repository at this point in the history
  • Loading branch information
polina-c committed Jul 11, 2023
1 parent 8e3aa07 commit a21e90e
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 4 deletions.
5 changes: 3 additions & 2 deletions doc/TROUBLESHOOT.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ if (ref.target == null) {
```

IMPORTANT: this code will not work in release mode, so
you need to run it with flag `--debug` or `--profile`, or,
if it is test, by clicking `Debug` near your test name in IDE.
you need to run it with flag `--debug` or `--profile`
([not available](https://github.com/flutter/flutter/issues/127331) for Flutter tests),
or, if it is a test, by clicking `Debug` near the test name in IDE.

## Known complicated cases

Expand Down
4 changes: 4 additions & 0 deletions pkgs/leak_tracker/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 7.0.7

* Protect from identityHashCode equal to 0.

# 7.0.6

* Add helpers for troubleshooting.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class ObjectTracker implements LeakProvider {
}) {
throwIfDisposed();
final code = _coder(object);
assert(code > 0);
if (_checkForDuplicate(code)) return;

_finalizer.attach(object, code);
Expand Down
3 changes: 3 additions & 0 deletions pkgs/leak_tracker/lib/src/leak_tracking/orchestration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ Future<void> forceGC({
/// If the object is garbage collected or not retained, returns null.
///
/// Does not work in web and in release mode.
///
/// Also does not work for objects that are not returned by getInstances.
/// https://github.com/dart-lang/sdk/blob/3e80d29fd6fec56187d651ce22ea81f1e8732214/runtime/vm/object_graph.cc#L1803
Future<String?> formattedRetainingPath(WeakReference ref) async {
if (ref.target == null) return null;
final path = await obtainRetainingPath(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@ import 'package:vm_service/vm_service.dart';

import '_connection.dart';

/// Obtains retainig path for an object.
///
/// Does not work for objects that have [identityHashCode] equal to 0.
/// https://github.com/dart-lang/sdk/blob/3e80d29fd6fec56187d651ce22ea81f1e8732214/runtime/vm/object_graph.cc#L1803
Future<RetainingPath?> obtainRetainingPath(Type type, int code) async {
assert(code > 0);

final connection = await connect();

final fp = _ObjectFingerprint(type, code);
Expand All @@ -26,7 +32,7 @@ Future<RetainingPath?> obtainRetainingPath(Type type, int code) async {
}

class _ObjectFingerprint {
_ObjectFingerprint(this.type, this.code);
_ObjectFingerprint(this.type, this.code) : assert(code > 0);

final Type type;
final int code;
Expand All @@ -39,6 +45,11 @@ class _ObjectFingerprint {
}
}

/// Finds and object in an isolate.
///
/// This method will NOT find objects, that have [identityHashCode] equal to 0
/// in result of `getInstances`.
/// https://github.com/dart-lang/sdk/blob/3e80d29fd6fec56187d651ce22ea81f1e8732214/runtime/vm/object_graph.cc#L1803
Future<_ItemInIsolate?> _objectInIsolate(
Connection connection,
_ObjectFingerprint object,
Expand All @@ -58,6 +69,9 @@ Future<_ItemInIsolate?> _objectInIsolate(
.instances ??
<ObjRef>[];

if (instances.isEmpty) continue;
assert(_refIsIdentifiable(instances.first));

final result = instances.firstWhereOrNull(
(objRef) =>
objRef is InstanceRef && objRef.identityHashCode == object.code,
Expand All @@ -73,6 +87,10 @@ Future<_ItemInIsolate?> _objectInIsolate(
return null;
}

bool _refIsIdentifiable(ObjRef ref) {
return ref is InstanceRef && (ref.identityHashCode ?? 0) > 0;
}

/// Represents an item in an isolate.
///
/// It can be class or object.
Expand Down
2 changes: 1 addition & 1 deletion pkgs/leak_tracker/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: leak_tracker
version: 7.0.6
version: 7.0.7
description: A framework for memory leak tracking for Dart and Flutter applications.
repository: https://github.com/dart-lang/leak_tracker/tree/main/pkgs/leak_tracker

Expand Down

0 comments on commit a21e90e

Please sign in to comment.