[#2280] Correct logic in Native.finishConnect. Fix use of optval parameter in c getOption function. In epoll event loop, check that channel is open before processing event.
This commit is contained in:
parent
01daefe925
commit
f62012cba5
@ -105,7 +105,7 @@ jint epollCtl(JNIEnv * env, jint efd, int op, jint fd, jint flags, jint id) {
|
|||||||
|
|
||||||
jint getOption(JNIEnv *env, jint fd, int level, int optname, const void *optval, socklen_t optlen) {
|
jint getOption(JNIEnv *env, jint fd, int level, int optname, const void *optval, socklen_t optlen) {
|
||||||
int code;
|
int code;
|
||||||
code = getsockopt(fd, level, optname, &optval, &optlen);
|
code = getsockopt(fd, level, optname, optval, &optlen);
|
||||||
if (code == 0) {
|
if (code == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -750,14 +750,28 @@ JNIEXPORT jboolean JNICALL Java_io_netty_channel_epoll_Native_connect(JNIEnv * e
|
|||||||
return JNI_TRUE;
|
return JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_finishConnect(JNIEnv * env, jclass clazz, jint fd) {
|
JNIEXPORT jboolean JNICALL Java_io_netty_channel_epoll_Native_finishConnect(JNIEnv * env, jclass clazz, jint fd) {
|
||||||
// connect done, check for error
|
// connect may be done
|
||||||
|
// return true if connection finished successfully
|
||||||
|
// return false if connection is still in progress
|
||||||
|
// throw exception if connection failed
|
||||||
int optval;
|
int optval;
|
||||||
int res = getOption(env, fd, SOL_SOCKET, SO_ERROR, &optval, sizeof(optval));
|
int res = getOption(env, fd, SOL_SOCKET, SO_ERROR, &optval, sizeof(optval));
|
||||||
if (res == 0) {
|
if (res != 0) {
|
||||||
return;
|
// getOption failed
|
||||||
|
throwIOException(env, exceptionMessage("finishConnect getOption failed: ", res));
|
||||||
|
return JNI_FALSE;
|
||||||
|
} else if (optval == EINPROGRESS) {
|
||||||
|
// connect still in progress
|
||||||
|
return JNI_FALSE;
|
||||||
|
} else if (optval == 0) {
|
||||||
|
// connect succeeded
|
||||||
|
return JNI_TRUE;
|
||||||
|
} else {
|
||||||
|
// connect failed
|
||||||
|
throwIOException(env, exceptionMessage("Unable to connect to remote host: ", optval));
|
||||||
|
return JNI_FALSE;
|
||||||
}
|
}
|
||||||
throwIOException(env, exceptionMessage("Unable to connect to remote host: ", optval));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_accept(JNIEnv * env, jclass clazz, jint fd) {
|
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_accept(JNIEnv * env, jclass clazz, jint fd) {
|
||||||
|
@ -42,7 +42,7 @@ jint Java_io_netty_channel_epoll_Native_socket(JNIEnv * env, jclass clazz);
|
|||||||
void Java_io_netty_channel_epoll_Native_bind(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port);
|
void Java_io_netty_channel_epoll_Native_bind(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port);
|
||||||
void Java_io_netty_channel_epoll_Native_listen(JNIEnv * env, jclass clazz, jint fd, jint backlog);
|
void Java_io_netty_channel_epoll_Native_listen(JNIEnv * env, jclass clazz, jint fd, jint backlog);
|
||||||
jboolean Java_io_netty_channel_epoll_Native_connect(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port);
|
jboolean Java_io_netty_channel_epoll_Native_connect(JNIEnv * env, jclass clazz, jint fd, jbyteArray address, jint scopeId, jint port);
|
||||||
void Java_io_netty_channel_epoll_Native_finishConnect(JNIEnv * env, jclass clazz, jint fd);
|
jboolean Java_io_netty_channel_epoll_Native_finishConnect(JNIEnv * env, jclass clazz, jint fd);
|
||||||
jint Java_io_netty_channel_epoll_Native_accept(JNIEnv * env, jclass clazz, jint fd);
|
jint Java_io_netty_channel_epoll_Native_accept(JNIEnv * env, jclass clazz, jint fd);
|
||||||
jlong Java_io_netty_channel_epoll_Native_sendfile(JNIEnv *env, jclass clazz, jint fd, jobject fileRegion, jlong off, jlong len);
|
jlong Java_io_netty_channel_epoll_Native_sendfile(JNIEnv *env, jclass clazz, jint fd, jobject fileRegion, jlong off, jlong len);
|
||||||
jobject Java_io_netty_channel_epoll_Native_remoteAddress(JNIEnv * env, jclass clazz, jint fd);
|
jobject Java_io_netty_channel_epoll_Native_remoteAddress(JNIEnv * env, jclass clazz, jint fd);
|
||||||
|
@ -323,15 +323,15 @@ final class EpollEventLoop extends SingleThreadEventLoop {
|
|||||||
AbstractEpollChannel ch = ids.get(id);
|
AbstractEpollChannel ch = ids.get(id);
|
||||||
if (ch != null) {
|
if (ch != null) {
|
||||||
AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe();
|
AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe();
|
||||||
if (write) {
|
if (write && ch.isOpen()) {
|
||||||
// force flush of data as the epoll is writable again
|
// force flush of data as the epoll is writable again
|
||||||
unsafe.epollOutReady();
|
unsafe.epollOutReady();
|
||||||
}
|
}
|
||||||
if (read) {
|
if (read && ch.isOpen()) {
|
||||||
// Something is ready to read, so consume it now
|
// Something is ready to read, so consume it now
|
||||||
unsafe.epollInReady();
|
unsafe.epollInReady();
|
||||||
}
|
}
|
||||||
if (close) {
|
if (close && ch.isOpen()) {
|
||||||
unsafe.epollRdHupReady();
|
unsafe.epollRdHupReady();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -485,9 +485,13 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
|
|||||||
|
|
||||||
assert eventLoop().inEventLoop();
|
assert eventLoop().inEventLoop();
|
||||||
|
|
||||||
|
boolean connectStillInProgress = false;
|
||||||
try {
|
try {
|
||||||
boolean wasActive = isActive();
|
boolean wasActive = isActive();
|
||||||
doFinishConnect();
|
if (!doFinishConnect()) {
|
||||||
|
connectStillInProgress = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
fulfillConnectPromise(connectPromise, wasActive);
|
fulfillConnectPromise(connectPromise, wasActive);
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if (t instanceof ConnectException) {
|
if (t instanceof ConnectException) {
|
||||||
@ -498,12 +502,14 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
|
|||||||
|
|
||||||
fulfillConnectPromise(connectPromise, t);
|
fulfillConnectPromise(connectPromise, t);
|
||||||
} finally {
|
} finally {
|
||||||
// Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used
|
if (!connectStillInProgress) {
|
||||||
// See https://github.com/netty/netty/issues/1770
|
// Check for null as the connectTimeoutFuture is only created if a connectTimeoutMillis > 0 is used
|
||||||
if (connectTimeoutFuture != null) {
|
// See https://github.com/netty/netty/issues/1770
|
||||||
connectTimeoutFuture.cancel(false);
|
if (connectTimeoutFuture != null) {
|
||||||
|
connectTimeoutFuture.cancel(false);
|
||||||
|
}
|
||||||
|
connectPromise = null;
|
||||||
}
|
}
|
||||||
connectPromise = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,9 +550,14 @@ public final class EpollSocketChannel extends AbstractEpollChannel implements So
|
|||||||
/**
|
/**
|
||||||
* Finish the connect
|
* Finish the connect
|
||||||
*/
|
*/
|
||||||
private void doFinishConnect() throws Exception {
|
private boolean doFinishConnect() throws Exception {
|
||||||
Native.finishConnect(fd);
|
if (Native.finishConnect(fd)) {
|
||||||
clearEpollOut();
|
clearEpollOut();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
setEpollOut();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +113,7 @@ final class Native {
|
|||||||
return connect(fd, address, scopeId, port);
|
return connect(fd, address, scopeId, port);
|
||||||
}
|
}
|
||||||
public static native boolean connect(int fd, byte[] address, int scopeId, int port) throws IOException;
|
public static native boolean connect(int fd, byte[] address, int scopeId, int port) throws IOException;
|
||||||
public static native void finishConnect(int fd) throws IOException;
|
public static native boolean finishConnect(int fd) throws IOException;
|
||||||
|
|
||||||
public static native InetSocketAddress remoteAddress(int fd);
|
public static native InetSocketAddress remoteAddress(int fd);
|
||||||
public static native InetSocketAddress localAddress(int fd);
|
public static native InetSocketAddress localAddress(int fd);
|
||||||
|
Loading…
Reference in New Issue
Block a user