8198928: (so) SocketChannel connect may deadlock if closed at around same time that connect fails

Reviewed-by: bpb, mli
This commit is contained in:
Alan Bateman 2018-03-07 07:13:55 +00:00
parent 1deb2a7bd5
commit 889a041f22
6 changed files with 258 additions and 152 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -293,8 +293,7 @@ Java_sun_nio_ch_Net_connect0(JNIEnv *env, jclass clazz, jboolean preferIPv6,
int sa_len = 0;
int rv;
if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len,
preferIPv6) != 0) {
if (NET_InetAddressToSockaddr(env, iao, port, &sa, &sa_len, preferIPv6) != 0) {
return IOS_THROWN;
}
@ -761,11 +760,11 @@ handleSocketError(JNIEnv *env, jint errorValue)
break;
#endif
case ECONNREFUSED:
xn = JNU_JAVANETPKG "ConnectException";
break;
case ETIMEDOUT:
case ENOTCONN:
xn = JNU_JAVANETPKG "ConnectException";
break;
case EHOSTUNREACH:
xn = JNU_JAVANETPKG "NoRouteToHostException";
break;

View file

@ -59,23 +59,29 @@ Java_sun_nio_ch_SocketChannelImpl_checkConnect(JNIEnv *env, jobject this,
poller.events = POLLOUT;
poller.revents = 0;
result = poll(&poller, 1, block ? -1 : 0);
if (result < 0) {
JNU_ThrowIOExceptionWithLastError(env, "Poll failed");
return IOS_THROWN;
if (errno == EINTR) {
return IOS_INTERRUPTED;
} else {
JNU_ThrowIOExceptionWithLastError(env, "poll failed");
return IOS_THROWN;
}
}
if (!block && (result == 0))
return IOS_UNAVAILABLE;
return IOS_UNAVAILABLE;
if (poller.revents) {
if (result > 0) {
errno = 0;
result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &n);
if (result < 0) {
handleSocketError(env, errno);
return JNI_FALSE;
return handleSocketError(env, errno);
} else if (error) {
handleSocketError(env, error);
return JNI_FALSE;
return handleSocketError(env, error);
} else if ((poller.revents & POLLHUP) != 0) {
return handleSocketError(env, ENOTCONN);
}
// connected
return 1;
}
return 0;