[io/socket] Handle OSError returned by Socket_GetPort.

Dart code did not expect OSError as a return value from Socket_GetPort.
This CL ensures that Dart code handles OSError in addition to int gracefully as a result of Socket_GetPort call.

Fixes https://github.com/dart-lang/sdk/issues/45116

TEST=run dart ci socket tests on mac with transparent proxy running

Change-Id: I198d99107729ccefecd9a16b71474ccdbfc0039b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193221
Reviewed-by: Siva Annamalai <asiva@google.com>
Commit-Queue: Alexander Aprelev <aam@google.com>
This commit is contained in:
Alexander Aprelev 2021-04-01 18:04:12 +00:00 committed by commit-bot@chromium.org
parent d5f3189c91
commit e190a85f49
8 changed files with 69 additions and 5 deletions

View file

@ -62,6 +62,7 @@ builtin_impl_sources = [
"thread_macos.h",
"thread_win.cc",
"thread_win.h",
"utils.cc",
"utils.h",
"utils_android.cc",
"utils_fuchsia.cc",

View file

@ -89,6 +89,7 @@ namespace bin {
V(Namespace_GetDefault, 0) \
V(Namespace_GetPointer, 1) \
V(NetworkInterface_ListSupported, 0) \
V(OSError_inProgressErrorCode, 0) \
V(Platform_NumberOfProcessors, 0) \
V(Platform_OperatingSystem, 0) \
V(Platform_OperatingSystemVersion, 0) \

25
runtime/bin/utils.cc Normal file
View file

@ -0,0 +1,25 @@
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "bin/utils.h"
#include <errno.h> // NOLINT
#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "include/dart_api.h"
#include "platform/globals.h"
#include "platform/utils.h"
namespace dart {
namespace bin {
void FUNCTION_NAME(OSError_inProgressErrorCode)(Dart_NativeArguments args) {
Dart_SetIntegerReturnValue(args, EINPROGRESS);
}
} // namespace bin
} // namespace dart

View file

@ -219,6 +219,14 @@ bool _isDirectIOCapableTypedList(List<int> buffer) {
throw UnsupportedError("_isDirectIOCapableTypedList");
}
@patch
class OSError {
@patch
static int inProgressErrorCode() {
throw new UnsupportedError("OSError.inProgressErrorCode");
}
}
@patch
class _IOCrypto {
@patch

View file

@ -227,6 +227,14 @@ class _IOCrypto {
}
}
@patch
class OSError {
@patch
static int inProgressErrorCode() {
throw new UnsupportedError("OSError.inProgressErrorCode");
}
}
@patch
class _Platform {
@patch

View file

@ -62,6 +62,12 @@ bool _isDirectIOCapableTypedList(List<int> buffer) {
classID == ClassID.cidUint8ClampedArray;
}
@patch
class OSError {
@patch
static int inProgressErrorCode() native "OSError_inProgressErrorCode";
}
@patch
class _IOCrypto {
@patch

View file

@ -802,9 +802,17 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
try {
socket.port;
} catch (e) {
error ??= createError(e, "Connection failed", address, port);
connectNext(); // Try again after failure to connect.
return;
if (e is OSError && e.errorCode == OSError.inProgressErrorCode()) {
// Ignore the error, proceed with waiting for a socket to become open.
// In non-blocking mode connect might not be established away, socket
// have to be waited for.
// EINPROGRESS error is ignored during |connect| call in native code,
// it has be ignored here during |port| query here.
} else {
error ??= createError(e, "Connection failed", address, port);
connectNext(); // Try again after failure to connect.
return;
}
}
// Try again if no response (failure or success) within a duration.
@ -1146,7 +1154,11 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
if (localAddress.type == InternetAddressType.unix) return 0;
if (localPort != 0) return localPort;
if (isClosing || isClosed) throw const SocketException.closed();
return localPort = nativeGetPort();
var result = nativeGetPort();
if (result is OSError) {
throw result;
}
return localPort = result;
}
int get remotePort {
@ -1530,7 +1542,7 @@ class _NativeSocket extends _NativeSocketNativeWrapper with _ServiceObject {
nativeCreateBindDatagram(Uint8List addr, int port, bool reuseAddress,
bool reusePort, int ttl) native "Socket_CreateBindDatagram";
bool nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
int nativeGetPort() native "Socket_GetPort";
dynamic nativeGetPort() native "Socket_GetPort";
List nativeGetRemotePeer() native "Socket_GetRemotePeer";
int nativeGetSocketId() native "Socket_GetSocketId";
OSError nativeGetError() native "Socket_GetError";

View file

@ -48,6 +48,9 @@ class OSError implements Exception {
/// Constant used to indicate that no OS error code is available.
static const int noErrorCode = -1;
/// Returns error code that corresponds to EINPROGRESS OS error.
external static int inProgressErrorCode();
/// Error message supplied by the operating system. This will be empty if no
/// message is associated with the error.
final String message;