[#3848] Respect EPOLLERR event
Motivation: Some glibc/kernel versions will trigger an EPOLLERR event to notify about failed connect and not an EPOLLOUT. Also EPOLLERR may be triggered when a connection is broke. Modification: React on EPOLLERR like if an EPOLLOUT / EPOLLIN was received, this will work in all cases as we handle errors in EPOLLOUT / EPOLLIN anyway. Result: Correctly detect errors.
This commit is contained in:
parent
d2615ab532
commit
49643fb5b1
@ -1615,6 +1615,10 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollrdhup(JNIEnv* env
|
|||||||
return EPOLLRDHUP;
|
return EPOLLRDHUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollerr(JNIEnv* env, jclass clazz) {
|
||||||
|
return EPOLLERR;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_sizeofEpollEvent(JNIEnv* env, jclass clazz) {
|
JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_sizeofEpollEvent(JNIEnv* env, jclass clazz) {
|
||||||
return sizeof(struct epoll_event);
|
return sizeof(struct epoll_event);
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,7 @@ jint Java_io_netty_channel_epoll_Native_epollin(JNIEnv* env, jclass clazz);
|
|||||||
jint Java_io_netty_channel_epoll_Native_epollout(JNIEnv* env, jclass clazz);
|
jint Java_io_netty_channel_epoll_Native_epollout(JNIEnv* env, jclass clazz);
|
||||||
jint Java_io_netty_channel_epoll_Native_epollrdhup(JNIEnv* env, jclass clazz);
|
jint Java_io_netty_channel_epoll_Native_epollrdhup(JNIEnv* env, jclass clazz);
|
||||||
jint Java_io_netty_channel_epoll_Native_epollet(JNIEnv* env, jclass clazz);
|
jint Java_io_netty_channel_epoll_Native_epollet(JNIEnv* env, jclass clazz);
|
||||||
|
jint Java_io_netty_channel_epoll_Native_epollerr(JNIEnv* env, jclass clazz);
|
||||||
jint Java_io_netty_channel_epoll_Native_sizeofEpollEvent(JNIEnv* env, jclass clazz);
|
jint Java_io_netty_channel_epoll_Native_sizeofEpollEvent(JNIEnv* env, jclass clazz);
|
||||||
jint Java_io_netty_channel_epoll_Native_offsetofEpollData(JNIEnv* env, jclass clazz);
|
jint Java_io_netty_channel_epoll_Native_offsetofEpollData(JNIEnv* env, jclass clazz);
|
||||||
|
|
||||||
|
@ -315,10 +315,18 @@ final class EpollEventLoop extends SingleThreadEventLoop {
|
|||||||
// past.
|
// past.
|
||||||
AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe();
|
AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe();
|
||||||
|
|
||||||
|
// Check if an error was the cause of the wakeup.
|
||||||
|
boolean err = (ev & Native.EPOLLERR) != 0;
|
||||||
|
|
||||||
// First check for EPOLLOUT as we may need to fail the connect ChannelPromise before try
|
// First check for EPOLLOUT as we may need to fail the connect ChannelPromise before try
|
||||||
// to read from the file descriptor.
|
// to read from the file descriptor.
|
||||||
// See https://github.com/netty/netty/issues/3785
|
// See https://github.com/netty/netty/issues/3785
|
||||||
if ((ev & Native.EPOLLOUT) != 0 && ch.isOpen()) {
|
//
|
||||||
|
// It is possible for an EPOLLOUT or EPOLLERR to be generated when a connection is refused.
|
||||||
|
// In either case epollOutReady() will do the correct thing (finish connecting, or fail
|
||||||
|
// the connection).
|
||||||
|
// See https://github.com/netty/netty/issues/3848
|
||||||
|
if (err || ((ev & Native.EPOLLOUT) != 0) && 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();
|
||||||
}
|
}
|
||||||
@ -329,7 +337,11 @@ final class EpollEventLoop extends SingleThreadEventLoop {
|
|||||||
if ((ev & Native.EPOLLRDHUP) != 0) {
|
if ((ev & Native.EPOLLRDHUP) != 0) {
|
||||||
unsafe.epollRdHupReady();
|
unsafe.epollRdHupReady();
|
||||||
}
|
}
|
||||||
if ((ev & Native.EPOLLIN) != 0 && ch.isOpen()) {
|
|
||||||
|
// If EPOLLOUT or EPOLLING was received and the channel is still open call epollInReady().
|
||||||
|
// This will try to read from the underlying filedescriptor and so notify the user about the
|
||||||
|
// error.
|
||||||
|
if ((err || (ev & Native.EPOLLIN) != 0) && ch.isOpen()) {
|
||||||
// The Channel is still open and there is something to read. Do it now.
|
// The Channel is still open and there is something to read. Do it now.
|
||||||
unsafe.epollInReady();
|
unsafe.epollInReady();
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ public final class Native {
|
|||||||
public static final int EPOLLOUT = epollout();
|
public static final int EPOLLOUT = epollout();
|
||||||
public static final int EPOLLRDHUP = epollrdhup();
|
public static final int EPOLLRDHUP = epollrdhup();
|
||||||
public static final int EPOLLET = epollet();
|
public static final int EPOLLET = epollet();
|
||||||
|
public static final int EPOLLERR = epollerr();
|
||||||
|
|
||||||
public static final int IOV_MAX = iovMax();
|
public static final int IOV_MAX = iovMax();
|
||||||
public static final int UIO_MAX_IOV = uioMaxIov();
|
public static final int UIO_MAX_IOV = uioMaxIov();
|
||||||
@ -701,6 +702,7 @@ public final class Native {
|
|||||||
private static native int epollout();
|
private static native int epollout();
|
||||||
private static native int epollrdhup();
|
private static native int epollrdhup();
|
||||||
private static native int epollet();
|
private static native int epollet();
|
||||||
|
private static native int epollerr();
|
||||||
|
|
||||||
private static native long ssizeMax();
|
private static native long ssizeMax();
|
||||||
private Native() {
|
private Native() {
|
||||||
|
Loading…
Reference in New Issue
Block a user