Index: third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart |
diff --git a/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart b/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart |
index f69c981b4fa06314db4ad4bb75443e5f3adb86e3..198a9f66fc3c80025856674d4ac0304994e33847 100644 |
--- a/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart |
+++ b/third_party/mojo/src/mojo/public/dart/src/handle_watcher.dart |
@@ -7,10 +7,10 @@ part of core; |
class _MojoHandleWatcherNatives { |
static int sendControlData(int controlHandle, int mojoHandle, SendPort port, |
int data) native "MojoHandleWatcher_SendControlData"; |
- static List recvControlData(int controlHandle) native |
- "MojoHandleWatcher_RecvControlData"; |
- static int setControlHandle(int controlHandle) native |
- "MojoHandleWatcher_SetControlHandle"; |
+ static List recvControlData( |
+ int controlHandle) native "MojoHandleWatcher_RecvControlData"; |
+ static int setControlHandle( |
+ int controlHandle) native "MojoHandleWatcher_SetControlHandle"; |
static int getControlHandle() native "MojoHandleWatcher_GetControlHandle"; |
} |
@@ -102,8 +102,7 @@ class MojoHandleWatcher { |
// Route event. |
watcher._routeEvent( |
- mwmr.states[mwmr.index].satisfied_signals, |
- mwmr.index); |
+ mwmr.states[mwmr.index].satisfied_signals, mwmr.index); |
// Remove the handle from the list. |
watcher._removeHandle(handle); |
} else if (!mwmr.result.isDeadlineExceeded) { |
@@ -134,7 +133,7 @@ class MojoHandleWatcher { |
_removeHandle(result[0]); |
break; |
case CLOSE: |
- _close(result[0]); |
+ _close(result[0], result[1]); |
break; |
case TIMER: |
_timer(result[1], result[0]); |
@@ -193,20 +192,25 @@ class MojoHandleWatcher { |
} |
} |
- void _close(int mojoHandle, {bool pruning: false}) { |
+ void _close(int mojoHandle, SendPort port, {bool pruning: false}) { |
+ assert(!pruning || (port == null)); |
int idx = _handleIndices[mojoHandle]; |
if (idx == null) { |
- // A client may request to close a handle that has already been closed on |
- // the other side and pruned, but before receiving notification from the |
- // handle watcher. |
+ // An app isolate may request that the handle watcher close a handle that |
+ // has already been pruned. This happens when the app isolate has not yet |
+ // received the PEER_CLOSED event. The app isolate will not close the |
+ // handle, so we must do so here. |
+ _tempHandle._set(mojoHandle); |
+ _tempHandle.close(); |
+ if (port != null) port.send(null); // Notify that close is done. |
return; |
} |
if (idx == 0) { |
throw "The control handle (idx = 0) cannot be closed."; |
} |
- _tempHandle.h = _handles[idx]; |
+ _tempHandle._set(_handles[idx]); |
_tempHandle.close(); |
- _tempHandle.h = MojoHandle.INVALID; |
+ if (port != null) port.send(null); // Notify that close is done. |
if (pruning) { |
// If this handle is being pruned, notify the application isolate |
// by sending MojoHandleSignals.PEER_CLOSED. |
@@ -223,9 +227,9 @@ class MojoHandleWatcher { |
_timerQueue.removeCurrent(); |
now = (new DateTime.now()).millisecondsSinceEpoch; |
} |
- return _timerQueue.hasTimer ? |
- (_timerQueue.currentTimeout - now) * 1000 : |
- MojoHandle.DEADLINE_INDEFINITE; |
+ return _timerQueue.hasTimer |
+ ? (_timerQueue.currentTimeout - now) * 1000 |
+ : MojoHandle.DEADLINE_INDEFINITE; |
} |
void _timer(SendPort port, int deadline) { |
@@ -241,16 +245,16 @@ class MojoHandleWatcher { |
closed.add(_handles[i]); |
} |
} else { |
- _tempHandle.h = _handles[i]; |
+ _tempHandle._set(_handles[i]); |
MojoWaitResult mwr = _tempHandle.wait(MojoHandleSignals.kAll, 0); |
if ((!mwr.result.isOk) && (!mwr.result.isDeadlineExceeded)) { |
closed.add(_handles[i]); |
} |
- _tempHandle.h = MojoHandle.INVALID; |
+ _tempHandle._set(MojoHandle.INVALID); |
} |
} |
for (var h in closed) { |
- _close(h, pruning: true); |
+ _close(h, null, pruning: true); |
} |
// '_close' updated the '_handles' array, so at this point the '_handles' |
// array and the caller's 'states' array are mismatched. |
@@ -258,14 +262,13 @@ class MojoHandleWatcher { |
void _shutdownHandleWatcher(SendPort shutdownSendPort) { |
_shutdown = true; |
- _tempHandle.h = _controlHandle; |
+ _tempHandle._set(_controlHandle); |
_tempHandle.close(); |
- _tempHandle.h = MojoHandle.INVALID; |
shutdownSendPort.send(null); |
} |
- static MojoResult _sendControlData(MojoHandle mojoHandle, SendPort port, |
- int data) { |
+ static MojoResult _sendControlData( |
+ MojoHandle mojoHandle, SendPort port, int data) { |
int controlHandle = _MojoHandleWatcherNatives.getControlHandle(); |
if (controlHandle == MojoHandle.INVALID) { |
return MojoResult.FAILED_PRECONDITION; |
@@ -276,10 +279,7 @@ class MojoHandleWatcher { |
rawHandle = mojoHandle.h; |
} |
var result = _MojoHandleWatcherNatives.sendControlData( |
- controlHandle, |
- rawHandle, |
- port, |
- data); |
+ controlHandle, rawHandle, port, data); |
return new MojoResult(result); |
} |
@@ -323,8 +323,26 @@ class MojoHandleWatcher { |
}); |
} |
- static MojoResult close(MojoHandle mojoHandle) { |
- return _sendControlData(mojoHandle, null, _encodeCommand(CLOSE)); |
+ // If wait is true, returns a future that resolves only after the handle |
+ // has actually been closed by the handle watcher. Otherwise, returns a |
+ // future that resolves immediately. |
+ static Future<MojoResult> close(MojoHandle mojoHandle, {bool wait: false}) { |
+ assert(MojoHandle._removeUnclosedHandle(mojoHandle)); |
+ if (!wait) { |
+ return new Future.value( |
+ _sendControlData(mojoHandle, null, _encodeCommand(CLOSE))); |
+ } |
+ MojoResult result; |
+ var completer = new Completer(); |
+ var rawPort = new RawReceivePort((_) { |
+ completer.complete(result); |
+ }); |
+ result = |
+ _sendControlData(mojoHandle, rawPort.sendPort, _encodeCommand(CLOSE)); |
+ return completer.future.then((r) { |
+ rawPort.close(); |
+ return r; |
+ }); |
} |
static MojoResult add(MojoHandle mojoHandle, SendPort port, int signals) { |
@@ -338,8 +356,6 @@ class MojoHandleWatcher { |
static MojoResult timer(Object ignored, SendPort port, int deadline) { |
// The deadline will be unwrapped before sending to the handle watcher. |
return _sendControlData( |
- new MojoHandle(deadline), |
- port, |
- _encodeCommand(TIMER)); |
+ new MojoHandle._internal(deadline), port, _encodeCommand(TIMER)); |
} |
} |