[#3457] Proper fix for IllegalStateException caused by closed file descriptor / channel

Motivation:

During 6b941e9bdb I introduced a regression that could cause an IllegalStateException.
A non-proper fix was commited as part of #3443. This commit add a proper fix.

Modifications:

Remove FileDescriptor.INVALID and add FileDescriptor.isOpen() as replacement. Once FileDescriptor.close() is called isOpen() will return false.

Result:

No more IllegalStateException caused by a close channel.
This commit is contained in:
Norman Maurer 2015-03-01 19:36:31 +01:00
parent 3ac08a07af
commit 0985e07845
4 changed files with 17 additions and 22 deletions

View File

@ -35,7 +35,7 @@ import java.nio.channels.UnresolvedAddressException;
abstract class AbstractEpollChannel extends AbstractChannel implements UnixChannel {
private static final ChannelMetadata DATA = new ChannelMetadata(false);
private final int readFlag;
private volatile FileDescriptor fileDescriptor;
private final FileDescriptor fileDescriptor;
protected int flags = Native.EPOLLET;
protected volatile boolean active;
@ -103,8 +103,7 @@ abstract class AbstractEpollChannel extends AbstractChannel implements UnixChann
doDeregister();
FileDescriptor fd = fileDescriptor;
fileDescriptor = FileDescriptor.INVALID;
Native.close(fd.intValue());
fd.close();
}
@Override
@ -119,7 +118,7 @@ abstract class AbstractEpollChannel extends AbstractChannel implements UnixChann
@Override
public boolean isOpen() {
return fileDescriptor != FileDescriptor.INVALID;
return fileDescriptor.isOpen();
}
@Override

View File

@ -97,7 +97,7 @@ public final class EpollDatagramChannel extends AbstractEpollChannel implements
@Override
@SuppressWarnings("deprecation")
public boolean isActive() {
return fd() != FileDescriptor.INVALID &&
return fd().isOpen() &&
(config.getOption(ChannelOption.DATAGRAM_CHANNEL_ACTIVE_ON_REGISTRATION) && isRegistered()
|| active);
}

View File

@ -24,6 +24,7 @@ import java.io.IOException;
public class FileDescriptor {
private final int fd;
private volatile boolean open = true;
public FileDescriptor(int fd) {
if (fd < 0) {
@ -32,21 +33,6 @@ public class FileDescriptor {
this.fd = fd;
}
/**
* An invalid file descriptor which was closed before.
*/
public static final FileDescriptor INVALID = new FileDescriptor(0) {
@Override
public int intValue() {
throw new IllegalStateException("invalid file descriptor");
}
@Override
public void close() {
// NOOP
}
};
/**
* Return the int value of the filedescriptor.
*/
@ -58,9 +44,17 @@ public class FileDescriptor {
* Close the file descriptor.
*/
public void close() throws IOException {
open = false;
close(fd);
}
/**
* Returns {@code true} if the file descriptor is open.
*/
public boolean isOpen() {
return open;
}
@Override
public String toString() {
return "FileDescriptor{" +

View File

@ -93,8 +93,10 @@ public class EpollDomainSocketFdTest extends AbstractSocketTest {
sc.close().sync();
if (received instanceof FileDescriptor) {
Assert.assertNotSame(FileDescriptor.INVALID, received);
((FileDescriptor) received).close();
FileDescriptor fd = (FileDescriptor) received;
Assert.assertTrue(fd.isOpen());
fd.close();
Assert.assertFalse(fd.isOpen());
Assert.assertNull(queue.poll());
} else {
throw (Throwable) received;