| Index: runtime/bin/socket_patch.dart
|
| diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
|
| index d10f3ae710576ff4fd5d22f7c942cc51fc789d99..44cedfe9712270e5ebcc599f160cda6b728f6f8a 100644
|
| --- a/runtime/bin/socket_patch.dart
|
| +++ b/runtime/bin/socket_patch.dart
|
| @@ -111,8 +111,9 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| static const int WRITE_EVENT = 1;
|
| static const int ERROR_EVENT = 2;
|
| static const int CLOSED_EVENT = 3;
|
| + static const int DESTROYED_EVENT = 4;
|
| static const int FIRST_EVENT = READ_EVENT;
|
| - static const int LAST_EVENT = CLOSED_EVENT;
|
| + static const int LAST_EVENT = DESTROYED_EVENT;
|
| static const int EVENT_COUNT = LAST_EVENT - FIRST_EVENT + 1;
|
|
|
| static const int CLOSE_COMMAND = 8;
|
| @@ -134,6 +135,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
|
|
| // Socket close state
|
| bool isClosed = false;
|
| + bool isClosing = false;
|
| bool isClosedRead = false;
|
| bool isClosedWrite = false;
|
| Completer closeCompleter = new Completer();
|
| @@ -261,7 +263,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| }
|
|
|
| int available() {
|
| - if (isClosed) return 0;
|
| + if (isClosing || isClosed) return 0;
|
| var result = nativeAvailable();
|
| if (result is OSError) {
|
| reportError(result, "Available failed");
|
| @@ -275,7 +277,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| if (len != null && len <= 0) {
|
| throw new ArgumentError("Illegal length $len");
|
| }
|
| - if (isClosed) return null;
|
| + if (isClosing || isClosed) return null;
|
| var result = nativeRead(len == null ? -1 : len);
|
| if (result is OSError) {
|
| reportError(result, "Read failed");
|
| @@ -296,7 +298,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| if (offset is! int || bytes is! int) {
|
| throw new ArgumentError("Invalid arguments to write on Socket");
|
| }
|
| - if (isClosed) return 0;
|
| + if (isClosing || isClosed) return 0;
|
| if (bytes == 0) return 0;
|
| _BufferAndStart bufferAndStart =
|
| _ensureFastAndSerializableBuffer(buffer, offset, offset + bytes);
|
| @@ -337,11 +339,20 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| if (((events & (1 << i)) != 0)) {
|
| if (i == CLOSED_EVENT &&
|
| typeFlags != TYPE_LISTENING_SOCKET &&
|
| + !isClosing &&
|
| !isClosed) {
|
| isClosedRead = true;
|
| }
|
|
|
| var handler = eventHandlers[i];
|
| + if (i == DESTROYED_EVENT) {
|
| + assert(!isClosed);
|
| + isClosed = true;
|
| + closeCompleter.complete(this);
|
| + disconnectFromEventHandler();
|
| + if (handler != null) handler();
|
| + continue;
|
| + }
|
| assert(handler != null);
|
| if (i == WRITE_EVENT) {
|
| // If the event was disabled before we had a chance to fire the event,
|
| @@ -372,11 +383,12 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| activateHandlers();
|
| }
|
|
|
| - void setHandlers({read: null, write: null, error: null, closed: null}) {
|
| + void setHandlers({read, write, error, closed, destroyed}) {
|
| eventHandlers[READ_EVENT] = read;
|
| eventHandlers[WRITE_EVENT] = write;
|
| eventHandlers[ERROR_EVENT] = error;
|
| eventHandlers[CLOSED_EVENT] = closed;
|
| + eventHandlers[DESTROYED_EVENT] = destroyed;
|
| }
|
|
|
| void setListening({read: true, write: true}) {
|
| @@ -386,37 +398,39 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| activateHandlers();
|
| }
|
|
|
| - Future get closeFuture => closeCompleter.future;
|
| + Future<_NativeSocket> get closeFuture => closeCompleter.future;
|
|
|
| void activateHandlers() {
|
| if (canActivateEvents && !isClosed) {
|
| - // If we don't listen for either read or write, disconnect as we won't
|
| - // get close and error events anyway.
|
| - if ((eventMask & ((1 << READ_EVENT) | (1 << WRITE_EVENT))) == 0) {
|
| + if (!isClosing &&
|
| + (eventMask & ((1 << READ_EVENT) | (1 << WRITE_EVENT))) == 0) {
|
| + // If we don't listen for either read or write, disconnect as we won't
|
| + // get close and error events anyway.
|
| if (eventPort != null) disconnectFromEventHandler();
|
| } else {
|
| int data = eventMask;
|
| + if (isClosing) {
|
| + data = 1 << DESTROYED_EVENT;
|
| + } else {
|
| + if (isClosedRead) data &= ~(1 << READ_EVENT);
|
| + if (isClosedWrite) data &= ~(1 << WRITE_EVENT);
|
| + }
|
| data |= typeFlags;
|
| - if (isClosedRead) data &= ~(1 << READ_EVENT);
|
| - if (isClosedWrite) data &= ~(1 << WRITE_EVENT);
|
| sendToEventHandler(data);
|
| }
|
| }
|
| }
|
|
|
| - void close() {
|
| - if (!isClosed) {
|
| + Future<_NativeSocket> close() {
|
| + if (!isClosing && !isClosed) {
|
| sendToEventHandler(1 << CLOSE_COMMAND);
|
| - isClosed = true;
|
| - closeCompleter.complete(this);
|
| + isClosing = true;
|
| }
|
| - // Outside the if support closing sockets created but never
|
| - // assigned any actual socket.
|
| - disconnectFromEventHandler();
|
| + return closeFuture;
|
| }
|
|
|
| void shutdown(SocketDirection direction) {
|
| - if (!isClosed) {
|
| + if (!isClosing && !isClosed) {
|
| switch (direction) {
|
| case SocketDirection.RECEIVE:
|
| shutdownRead();
|
| @@ -434,7 +448,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| }
|
|
|
| void shutdownWrite() {
|
| - if (!isClosed) {
|
| + if (!isClosing && !isClosed) {
|
| if (isClosedRead) {
|
| close();
|
| } else {
|
| @@ -445,7 +459,7 @@ class _NativeSocket extends NativeFieldWrapperClass1 {
|
| }
|
|
|
| void shutdownRead() {
|
| - if (!isClosed) {
|
| + if (!isClosing && !isClosed) {
|
| if (isClosedWrite) {
|
| close();
|
| } else {
|
| @@ -589,7 +603,7 @@ class _RawServerSocket extends Stream<RawSocket>
|
|
|
| int get port => _socket.port;
|
|
|
| - void close() => _socket.close();
|
| + Future close() => _socket.close().then((_) => this);
|
|
|
| void _pause() {
|
| _socket.setListening(read: false, write: false);
|
| @@ -645,6 +659,7 @@ class _RawSocket extends Stream<RawSocketEvent>
|
| _controller.add(RawSocketEvent.WRITE);
|
| },
|
| closed: () => _controller.add(RawSocketEvent.READ_CLOSED),
|
| + destroyed: () => _controller.add(RawSocketEvent.CLOSED),
|
| error: (e) {
|
| _controller.addError(e);
|
| close();
|
| @@ -684,7 +699,7 @@ class _RawSocket extends Stream<RawSocketEvent>
|
| int write(List<int> buffer, [int offset, int count]) =>
|
| _socket.write(buffer, offset, count);
|
|
|
| - void close() => _socket.close();
|
| + Future close() => _socket.close().then((_) => this);
|
|
|
| void shutdown(SocketDirection direction) => _socket.shutdown(direction);
|
|
|
| @@ -777,7 +792,7 @@ class _ServerSocket extends Stream<Socket>
|
|
|
| int get port => _socket.port;
|
|
|
| - void close() => _socket.close();
|
| + Future close() => _socket.close().then((_) => this);
|
| }
|
|
|
|
|
|
|