Chromium Code Reviews| Index: mojo/public/dart/src/handle.dart |
| diff --git a/mojo/public/dart/src/handle.dart b/mojo/public/dart/src/handle.dart |
| index 298ed1df090afe8122a388ee3c5703e39f6d44bd..6b99ed87aa79e929fe865fe076f3c51d8ba7881e 100644 |
| --- a/mojo/public/dart/src/handle.dart |
| +++ b/mojo/public/dart/src/handle.dart |
| @@ -13,20 +13,39 @@ class _MojoHandleNatives { |
| int deadline) native "MojoHandle_WaitMany"; |
| } |
| +class _HandleCreationRecord { |
| + final MojoHandle handle; |
| + final StackTrace stack; |
| + _HandleCreationRecord(this.handle, this.stack); |
| +} |
| + |
| class MojoHandle { |
| static const int INVALID = 0; |
| static const int DEADLINE_INDEFINITE = -1; |
| - int h; |
| + int _h; |
| + int get h => _h; |
| + |
| + MojoHandle(this._h) { |
| + assert(_addUnclosedHandle(this)); |
| + } |
| + |
| + MojoHandle._internal(this._h); |
| - MojoHandle(this.h); |
| + MojoHandle.invalid() : this._internal(INVALID); |
| MojoResult close() { |
| - int result = _MojoHandleNatives.close(h); |
| - h = INVALID; |
| + assert(_removeUnclosedHandle(this)); |
| + int result = _MojoHandleNatives.close(_h); |
| + _h = INVALID; |
| return new MojoResult(result); |
| } |
| + MojoHandle pass() { |
| + assert(_removeUnclosedHandle(this)); |
| + return this; |
| + } |
| + |
| MojoWaitResult wait(int signals, int deadline) { |
| List result = _MojoHandleNatives.wait(h, signals, deadline); |
| return new MojoWaitResult(new MojoResult(result[0]), result[1]); |
| @@ -44,12 +63,29 @@ class MojoHandle { |
| return false; |
| default: |
| // Should be unreachable. |
| - throw "Unexpected result $res for wait on $h"; |
| + throw "Unexpected result $mwr for wait on $h"; |
| } |
| } |
| + void _set(int value) { |
| + _h = value; |
| + } |
| + |
| bool get readyRead => _ready(MojoHandleSignals.PEER_CLOSED_READABLE); |
| bool get readyWrite => _ready(MojoHandleSignals.WRITABLE); |
| + bool get isValid => (_h != INVALID); |
| + |
| + String toString() { |
| + if (!isValid) { |
| + return "MojoHandle(INVALID)"; |
| + } |
| + var mwr = wait(MojoHandleSignals.kAll, 0); |
| + return "MojoHandle(h: $h, status: $mwr)"; |
| + } |
| + |
| + bool operator ==(MojoHandle other) { |
| + return _h == other._h; |
| + } |
| static MojoWaitManyResult waitMany( |
| List<int> handles, List<int> signals, int deadline) { |
| @@ -62,17 +98,38 @@ class MojoHandle { |
| return new MojoResult(_MojoHandleNatives.register(eventStream)); |
| } |
| - bool get isValid => (h != INVALID); |
| + static HashMap<int, _HandleCreationRecord> _unclosedHandles = new HashMap(); |
| - String toString() { |
| - if (!isValid) { |
| - return "MojoHandle(INVALID)"; |
| + // _addUnclosedHandle(), _removeUnclosedHandle(), and dumpLeakedHandles() |
| + // should only be used inside of assert() statements. |
| + static bool _addUnclosedHandle(MojoHandle handle) { |
| + var stack; |
| + try { |
| + assert(false); |
|
sky
2015/03/11 17:17:57
Ick.
zra
2015/03/11 18:58:20
In case someone accidentally uses one of these cal
|
| + } catch (_, s) { |
| + stack = s; |
| } |
| - var mwr = wait(MojoHandleSignals.kAll, 0); |
| - return "MojoHandle(h: $h, status: $mwr)"; |
| + |
| + var handleCreate = new _HandleCreationRecord(handle, stack); |
| + _unclosedHandles[handle.h] = handleCreate; |
| + return true; |
|
sky
2015/03/11 17:17:57
Is there a reason you have a return value here sin
zra
2015/03/11 18:58:20
Making these calls only inside of assert() stateme
sky
2015/03/11 19:17:24
Ah, tricky. Got it.
|
| } |
| - bool operator ==(MojoHandle other) { |
| - return h == other.h; |
| + static bool _removeUnclosedHandle(MojoHandle handle) { |
| + _unclosedHandles.remove(handle._h); |
| + return true; |
|
sky
2015/03/11 17:17:57
Same comment here about always true return value.
zra
2015/03/11 18:58:20
Same reason.
|
| + } |
| + |
| + static bool reportLeakedHandles() { |
| + var noleaks = true; |
| + for (var handle in MojoHandle._unclosedHandles.keys) { |
| + var handleCreation = MojoHandle._unclosedHandles[handle]; |
| + if (handleCreation != null) { |
| + print("HANDLE LEAK: handle: $handle, created at:"); |
| + print("${handleCreation.stack}"); |
| + noleaks = false; |
| + } |
| + } |
| + return noleaks; |
| } |
| } |