diff --git a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml
index 80f7291f71..fdab2d5571 100644
--- a/transport-native-epoll/pom.xml
+++ b/transport-native-epoll/pom.xml
@@ -34,6 +34,7 @@
${project.build.directory}/unix-common-lib
${unix.common.lib.dir}/META-INF/native/lib
${unix.common.lib.dir}/META-INF/native/include
+ CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}
LDFLAGS=-L${unix.common.lib.unpacked.dir} -Wl,--no-as-needed -lrt -Wl,--whole-archive -l${unix.common.lib.name} -Wl,--no-whole-archive
${project.basedir}/src/main/c
true
@@ -192,102 +193,6 @@
-
-
- maven-antrun-plugin
-
-
-
- validate
-
- run
-
- ant-get-systeminfo
-
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.codehaus.mojo
- build-helper-maven-plugin
-
-
-
- initialize
- regex-glibc-sendmmsg
-
- regex-property
-
-
- glibc.sendmmsg.support
- ${ldd_version}
-
- ^((?!^[^)]+\)\s+(0*2\.1[4-9]|0*2\.[2-9][0-9]+|0*[3-9][0-9]*|0*[1-9]+[0-9]+).*).)*$
- IO_NETTY_SENDMSSG_NOT_FOUND
- false
-
-
-
-
- initialize
- regex-linux-sendmmsg
-
- regex-property
-
-
- linux.sendmmsg.support
- ${uname_os_version}
-
- ^((?!^[0-9]*[3-9]\.?.*).)*$
- IO_NETTY_SENDMSSG_NOT_FOUND
- false
-
-
-
-
- generate-sources
- regex-combined-sendmmsg
-
- regex-property
-
-
- jni.compiler.args.cflags
- ${linux.sendmmsg.support}${glibc.sendmmsg.support}
-
- .*IO_NETTY_SENDMSSG_NOT_FOUND.*
- CFLAGS=-O3 -DIO_NETTY_SENDMMSG_NOT_FOUND -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}
- false
-
-
-
-
- generate-sources
- regex-unset-if-needed-sendmmsg
-
- regex-property
-
-
- jni.compiler.args.cflags
- ${jni.compiler.args.cflags}
-
- ^((?!CFLAGS=).)*$
- CFLAGS=-O3 -Werror -fno-omit-frame-pointer -Wunused-variable -fvisibility=hidden -I${unix.common.include.unpacked.dir}
- false
-
-
-
-
diff --git a/transport-native-epoll/src/main/c/netty_epoll_native.c b/transport-native-epoll/src/main/c/netty_epoll_native.c
index cac6472a16..22635489b6 100644
--- a/transport-native-epoll/src/main/c/netty_epoll_native.c
+++ b/transport-native-epoll/src/main/c/netty_epoll_native.c
@@ -36,6 +36,9 @@
#include
#include
#include
+// Needed to be able to use syscalls directly and so not depend on newer GLIBC versions
+#include
+#include
#include "netty_epoll_linuxsocket.h"
#include "netty_unix_buffer.h"
@@ -54,15 +57,20 @@
// optional
extern int epoll_create1(int flags) __attribute__((weak));
-#ifdef IO_NETTY_SENDMMSG_NOT_FOUND
-extern int sendmmsg(int sockfd, struct mmsghdr* msgvec, unsigned int vlen, unsigned int flags) __attribute__((weak));
-
#ifndef __USE_GNU
struct mmsghdr {
struct msghdr msg_hdr; /* Message header */
unsigned int msg_len; /* Number of bytes transmitted */
};
#endif
+
+// All linux syscall numbers are stable so this is safe.
+#ifndef SYS_recvmmsg
+#define SYS_recvmmsg 299
+#endif
+
+#ifndef SYS_sendmmsg
+#define SYS_sendmmsg 307
#endif
// Those are initialized in the init(...) method and cached for performance reasons
@@ -305,7 +313,8 @@ static jint netty_epoll_native_sendmmsg0(JNIEnv* env, jclass clazz, jint fd, jbo
ssize_t res;
int err;
do {
- res = sendmmsg(fd, msg, len, 0);
+ // We directly use the syscall to prevent depending on GLIBC 2.14.
+ res = syscall(SYS_sendmmsg, fd, msg, len, 0);
// keep on writing if it was interrupted
} while (res == -1 && ((err = errno) == EINTR));
@@ -336,8 +345,10 @@ static jint netty_epoll_native_recvmmsg0(JNIEnv* env, jclass clazz, jint fd, jbo
ssize_t res;
int err;
do {
- res = recvmmsg(fd, msg, len, 0, NULL);
- // keep on reading if it was interrupted
+ // We directly use the syscall to prevent depending on GLIBC 2.12.
+ res = syscall(SYS_recvmmsg, fd, &msg, len, 0, NULL);
+
+ // keep on reading if it was interrupted
} while (res == -1 && ((err = errno) == EINTR));
if (res < 0) {
@@ -388,14 +399,22 @@ static jstring netty_epoll_native_kernelVersion(JNIEnv* env, jclass clazz) {
netty_unix_errors_throwRuntimeExceptionErrorNo(env, "uname() failed: ", errno);
return NULL;
}
-
static jboolean netty_epoll_native_isSupportingSendmmsg(JNIEnv* env, jclass clazz) {
- // Use & to avoid warnings with -Wtautological-pointer-compare when sendmmsg is
- // not weakly defined.
- if (&sendmmsg != NULL) {
- return JNI_TRUE;
+ if (syscall(SYS_sendmmsg, -1, NULL, 0, 0) == -1) {
+ if (errno == ENOSYS) {
+ return JNI_FALSE;
+ }
}
- return JNI_FALSE;
+ return JNI_TRUE;
+}
+
+static jboolean netty_epoll_native_isSupportingRecvmmsg(JNIEnv* env, jclass clazz) {
+ if (syscall(SYS_recvmmsg, -1, NULL, 0, 0, NULL) == -1) {
+ if (errno == ENOSYS) {
+ return JNI_FALSE;
+ }
+ }
+ return JNI_TRUE;
}
static jboolean netty_epoll_native_isSupportingTcpFastopen(JNIEnv* env, jclass clazz) {
@@ -476,6 +495,7 @@ static const JNINativeMethod statically_referenced_fixed_method_table[] = {
{ "epollerr", "()I", (void *) netty_epoll_native_epollerr },
{ "tcpMd5SigMaxKeyLen", "()I", (void *) netty_epoll_native_tcpMd5SigMaxKeyLen },
{ "isSupportingSendmmsg", "()Z", (void *) netty_epoll_native_isSupportingSendmmsg },
+ { "isSupportingRecvmmsg", "()Z", (void *) netty_epoll_native_isSupportingRecvmmsg },
{ "isSupportingTcpFastopen", "()Z", (void *) netty_epoll_native_isSupportingTcpFastopen },
{ "kernelVersion", "()Ljava/lang/String;", (void *) netty_epoll_native_kernelVersion }
};
diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java
index 26090d0809..c1f95dd6a3 100644
--- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java
+++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollDatagramChannel.java
@@ -483,7 +483,11 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
ByteBuf byteBuf = allocHandle.allocate(allocator);
final boolean read;
int datagramSize = config().getMaxDatagramPayloadSize();
- int numDatagram = datagramSize == 0 ? 1 : byteBuf.writableBytes() / datagramSize;
+
+ // Only try to use recvmmsg if its really supported by the running system.
+ int numDatagram = Native.IS_SUPPORTING_RECVMMSG ?
+ datagramSize == 0 ? 1 : byteBuf.writableBytes() / datagramSize :
+ 0;
try {
if (numDatagram <= 1) {
diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
index 9fb92aaf1c..32c9ba7f5b 100644
--- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
+++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/Native.java
@@ -32,6 +32,7 @@ import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epolle
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollin;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollout;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.epollrdhup;
+import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingRecvmmsg;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingSendmmsg;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.isSupportingTcpFastopen;
import static io.netty.channel.epoll.NativeStaticallyReferencedJniMethods.kernelVersion;
@@ -67,6 +68,8 @@ public final class Native {
public static final int EPOLLERR = epollerr();
public static final boolean IS_SUPPORTING_SENDMMSG = isSupportingSendmmsg();
+ static final boolean IS_SUPPORTING_RECVMMSG = isSupportingRecvmmsg();
+
public static final boolean IS_SUPPORTING_TCP_FASTOPEN = isSupportingTcpFastopen();
public static final int TCP_MD5SIG_MAXKEYLEN = tcpMd5SigMaxKeyLen();
public static final String KERNEL_VERSION = kernelVersion();
diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/NativeStaticallyReferencedJniMethods.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/NativeStaticallyReferencedJniMethods.java
index 4f6f99c528..9b20d686f0 100644
--- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/NativeStaticallyReferencedJniMethods.java
+++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/NativeStaticallyReferencedJniMethods.java
@@ -40,6 +40,7 @@ final class NativeStaticallyReferencedJniMethods {
static native int iovMax();
static native int uioMaxIov();
static native boolean isSupportingSendmmsg();
+ static native boolean isSupportingRecvmmsg();
static native boolean isSupportingTcpFastopen();
static native String kernelVersion();
}
diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramScatteringReadTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramScatteringReadTest.java
index d7f5d480c6..85f62f301f 100644
--- a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramScatteringReadTest.java
+++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollDatagramScatteringReadTest.java
@@ -25,6 +25,8 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.socket.AbstractDatagramTest;
+import org.junit.Assume;
+import org.junit.BeforeClass;
import org.junit.Test;
import java.net.InetSocketAddress;
@@ -43,6 +45,11 @@ import static org.junit.Assert.fail;
public class EpollDatagramScatteringReadTest extends AbstractDatagramTest {
+ @BeforeClass
+ public static void assumeRecvmmsgSupported() {
+ Assume.assumeTrue(Native.IS_SUPPORTING_RECVMMSG);
+ }
+
@Override
protected List> newFactories() {
return EpollSocketTestPermutation.INSTANCE.epollOnlyDatagram(internetProtocolFamily());