Index: third_party/mojo/src/mojo/public/dart/src/handle.dart |
diff --git a/third_party/mojo/src/mojo/public/dart/src/handle.dart b/third_party/mojo/src/mojo/public/dart/src/handle.dart |
index 53d0fe8bb05b5933254da0e69989727f86983205..6b99ed87aa79e929fe865fe076f3c51d8ba7881e 100644 |
--- a/third_party/mojo/src/mojo/public/dart/src/handle.dart |
+++ b/third_party/mojo/src/mojo/public/dart/src/handle.dart |
@@ -7,27 +7,45 @@ part of core; |
class _MojoHandleNatives { |
static int register(MojoEventStream eventStream) native "MojoHandle_Register"; |
static int close(int handle) native "MojoHandle_Close"; |
- static List wait(int handle, int signals, int deadline) native |
- "MojoHandle_Wait"; |
+ static List wait( |
+ int handle, int signals, int deadline) native "MojoHandle_Wait"; |
static List waitMany(List<int> handles, List<int> signals, |
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]); |
@@ -45,31 +63,73 @@ 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)"; |
+ } |
- static MojoWaitManyResult waitMany(List<int> handles, List<int> signals, |
- int deadline) { |
+ bool operator ==(MojoHandle other) { |
+ return _h == other._h; |
+ } |
+ |
+ static MojoWaitManyResult waitMany( |
+ List<int> handles, List<int> signals, int deadline) { |
List result = _MojoHandleNatives.waitMany(handles, signals, deadline); |
return new MojoWaitManyResult( |
- new MojoResult(result[0]), |
- result[1], |
- result[2]); |
+ new MojoResult(result[0]), result[1], result[2]); |
} |
static MojoResult register(MojoEventStream eventStream) { |
return new MojoResult(_MojoHandleNatives.register(eventStream)); |
} |
- bool get isValid => (h != INVALID); |
+ static HashMap<int, _HandleCreationRecord> _unclosedHandles = new HashMap(); |
- String toString() => "$h"; |
+ // _addUnclosedHandle(), _removeUnclosedHandle(), and dumpLeakedHandles() |
+ // should only be used inside of assert() statements. |
+ static bool _addUnclosedHandle(MojoHandle handle) { |
+ var stack; |
+ try { |
+ assert(false); |
+ } catch (_, s) { |
+ stack = s; |
+ } |
- bool operator ==(MojoHandle other) { |
- return h == other.h; |
+ var handleCreate = new _HandleCreationRecord(handle, stack); |
+ _unclosedHandles[handle.h] = handleCreate; |
+ return true; |
+ } |
+ |
+ static bool _removeUnclosedHandle(MojoHandle handle) { |
+ _unclosedHandles.remove(handle._h); |
+ return true; |
+ } |
+ |
+ 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; |
} |
} |