Looking at stack traces and the implementation sources, you might notice that the exception is thrown by the internal sun.nio.ch.UnixAsynchronousSocketChannelImpl#finish()
method which checks for pending read/write operations. So the only way to avoid this exception is to prevent new asynchronous read()
and write()
calls at some point, and that should be a part of the application's logic.
I've dealt with this exception quite a lot, and in most cases the root problem was in the completion handler's unconditional "continue listening" calls:
conn.read(src, attachment, new CompletionHandler<Integer, T>() {
@Override
public void completed(Integer result, T attachment) {
// Some business logic here
// Below is the problem - unconditional read() call
conn.read(src, attachment, this);
}
@Override
public void failed(Throwable t, T attachment) {
// Exception handling
}
});
To gracefully close the connection, there should be no unconditional async read/write calls. To achieve that, one might need to send an additional message which would mean that no new async data is expected and it's safe to close the connection. And the correct pseudo-code would look something like this:
conn.read(src, attachment, new CompletionHandler<Integer, T>() {
@Override
public void completed(Integer result, T attachment) {
// Some business logic here
if(continueListening()) {
conn.read(src, attachment, this);
}
}
// ...
});