Use ChannelException when ChannelConfig operation fails in epoll.

Motivation:

In NIO and OIO we throw a ChannelException if a ChannelConfig operation fails. We should do the same with epoll to be consistent.

Modifications:

Use ChannelException

Result:

Consistent behaviour across different transport implementations.
This commit is contained in:
Norman Maurer 2015-08-28 20:37:17 +02:00
parent 407d5ccdcf
commit 0c83542000
3 changed files with 83 additions and 7 deletions

View File

@ -16,6 +16,7 @@
void throwRuntimeException(JNIEnv* env, char* message);
void throwRuntimeExceptionErrorNo(JNIEnv* env, char* message, int errorNumber);
void throwChannelExceptionErrorNo(JNIEnv* env, char* message, int errorNumber);
void throwIOException(JNIEnv* env, char* message);
void throwIOExceptionErrorNo(JNIEnv* env, char* message, int errorNumber);
void throwClosedChannelException(JNIEnv* env);

View File

@ -86,6 +86,7 @@ jfieldID packetCountFieldId = NULL;
jmethodID inetSocketAddrMethodId = NULL;
jmethodID datagramSocketAddrMethodId = NULL;
jclass runtimeExceptionClass = NULL;
jclass channelExceptionClass = NULL;
jclass ioExceptionClass = NULL;
jclass closedChannelExceptionClass = NULL;
jmethodID closedChannelExceptionMethodId = NULL;
@ -109,6 +110,13 @@ void throwRuntimeExceptionErrorNo(JNIEnv* env, char* message, int errorNumber) {
free(allocatedMessage);
}
void throwChannelExceptionErrorNo(JNIEnv* env, char* message, int errorNumber) {
char* allocatedMessage = exceptionMessage(message, errorNumber);
(*env)->ThrowNew(env, channelExceptionClass, allocatedMessage);
free(allocatedMessage);
}
void throwIOException(JNIEnv* env, char* message) {
(*env)->ThrowNew(env, ioExceptionClass, message);
}
@ -163,7 +171,7 @@ static inline jint getOption(JNIEnv* env, jint fd, int level, int optname, void*
return 0;
}
int err = errno;
throwRuntimeExceptionErrorNo(env, "getsockopt() failed: ", err);
throwChannelExceptionErrorNo(env, "getsockopt() failed: ", err);
return code;
}
@ -171,7 +179,7 @@ static inline int setOption(JNIEnv* env, jint fd, int level, int optname, const
int rc = setsockopt(fd, level, optname, optval, len);
if (rc < 0) {
int err = errno;
throwRuntimeExceptionErrorNo(env, "setsockopt() failed: ", err);
throwChannelExceptionErrorNo(env, "setsockopt() failed: ", err);
}
return rc;
}
@ -392,6 +400,18 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return JNI_ERR;
}
jclass localChannelExceptionClass = (*env)->FindClass(env, "io/netty/channel/ChannelException");
if (localChannelExceptionClass == NULL) {
// pending exception...
return JNI_ERR;
}
channelExceptionClass = (jclass) (*env)->NewGlobalRef(env, localChannelExceptionClass);
if (channelExceptionClass == NULL) {
// out-of-memory!
throwOutOfMemoryError(env);
return JNI_ERR;
}
jclass localNetUtilClass = (*env)->FindClass(env, "io/netty/util/NetUtil" );
if (localNetUtilClass == NULL) {
// pending exception...
@ -619,6 +639,9 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
if (runtimeExceptionClass != NULL) {
(*env)->DeleteGlobalRef(env, runtimeExceptionClass);
}
if (channelExceptionClass != NULL) {
(*env)->DeleteGlobalRef(env, channelExceptionClass);
}
if (ioExceptionClass != NULL) {
(*env)->DeleteGlobalRef(env, ioExceptionClass);
}
@ -642,7 +665,7 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_eventFd(JNIEnv* env, j
if (eventFD < 0) {
int err = errno;
throwRuntimeExceptionErrorNo(env, "eventfd() failed: ", err);
throwChannelExceptionErrorNo(env, "eventfd() failed: ", err);
}
return eventFD;
}
@ -652,7 +675,7 @@ JNIEXPORT void JNICALL Java_io_netty_channel_epoll_Native_eventFdWrite(JNIEnv* e
if (eventFD < 0) {
int err = errno;
throwRuntimeExceptionErrorNo(env, "eventfd_write() failed: ", err);
throwChannelExceptionErrorNo(env, "eventfd_write() failed: ", err);
}
}
@ -676,9 +699,9 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv* en
if (efd < 0) {
int err = errno;
if (epoll_create1) {
throwRuntimeExceptionErrorNo(env, "epoll_create1() failed: ", err);
throwChannelExceptionErrorNo(env, "epoll_create1() failed: ", err);
} else {
throwRuntimeExceptionErrorNo(env, "epoll_create() failed: ", err);
throwChannelExceptionErrorNo(env, "epoll_create() failed: ", err);
}
return efd;
}
@ -686,7 +709,7 @@ JNIEXPORT jint JNICALL Java_io_netty_channel_epoll_Native_epollCreate(JNIEnv* en
if (fcntl(efd, F_SETFD, FD_CLOEXEC) < 0) {
int err = errno;
close(efd);
throwRuntimeExceptionErrorNo(env, "fcntl() failed: ", err);
throwChannelExceptionErrorNo(env, "fcntl() failed: ", err);
return err;
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright 2015 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.epoll;
import io.netty.channel.ChannelException;
import org.junit.Test;
import static org.junit.Assert.fail;
public class EpollChannelConfigTest {
@Test
public void testOptionGetThrowsChannelException() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
channel.config().getSoLinger();
channel.fd().close();
try {
channel.config().getSoLinger();
fail();
} catch (ChannelException e) {
// expected
}
}
@Test
public void testOptionSetThrowsChannelException() throws Exception {
Epoll.ensureAvailability();
EpollSocketChannel channel = new EpollSocketChannel();
channel.config().setKeepAlive(true);
channel.fd().close();
try {
channel.config().setKeepAlive(true);
fail();
} catch (ChannelException e) {
// expected
}
}
}