[#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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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_epollrdhup(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_offsetofEpollData(JNIEnv* env, jclass clazz);
|
||||
|
||||
|
@ -315,10 +315,18 @@ final class EpollEventLoop extends SingleThreadEventLoop {
|
||||
// past.
|
||||
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
|
||||
// to read from the file descriptor.
|
||||
// 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
|
||||
unsafe.epollOutReady();
|
||||
}
|
||||
@ -329,7 +337,11 @@ final class EpollEventLoop extends SingleThreadEventLoop {
|
||||
if ((ev & Native.EPOLLRDHUP) != 0) {
|
||||
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.
|
||||
unsafe.epollInReady();
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ public final class Native {
|
||||
public static final int EPOLLOUT = epollout();
|
||||
public static final int EPOLLRDHUP = epollrdhup();
|
||||
public static final int EPOLLET = epollet();
|
||||
public static final int EPOLLERR = epollerr();
|
||||
|
||||
public static final int IOV_MAX = iovMax();
|
||||
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 epollrdhup();
|
||||
private static native int epollet();
|
||||
private static native int epollerr();
|
||||
|
||||
private static native long ssizeMax();
|
||||
private Native() {
|
||||
|
Loading…
Reference in New Issue
Block a user