6878369: (ch) AsynchronousSocketChannel read/write methods that specify timeouts should not throw IAE
Reviewed-by: forax
This commit is contained in:
parent
fac39410b5
commit
b6b4b5086c
@ -110,7 +110,8 @@ import java.nio.ByteBuffer;
|
||||
* state of the {@link ByteBuffer}, or the sequence of buffers, for the I/O
|
||||
* operation is not defined. Buffers should be discarded or at least care must
|
||||
* be taken to ensure that the buffers are not accessed while the channel remains
|
||||
* open.
|
||||
* open. All methods that accept timeout parameters treat values less than or
|
||||
* equal to zero to mean that the I/O operation does not timeout.
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
@ -367,7 +368,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* @param dst
|
||||
* The buffer into which bytes are to be transferred
|
||||
* @param timeout
|
||||
* The timeout, or {@code 0L} for no timeout
|
||||
* The maximum time for the I/O operation to complete
|
||||
* @param unit
|
||||
* The time unit of the {@code timeout} argument
|
||||
* @param attachment
|
||||
@ -376,8 +377,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* The handler for consuming the result
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the {@code timeout} parameter is negative or the buffer is
|
||||
* read-only
|
||||
* If the buffer is read-only
|
||||
* @throws ReadPendingException
|
||||
* If a read operation is already in progress on this channel
|
||||
* @throws NotYetConnectedException
|
||||
@ -471,7 +471,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* The maximum number of buffers to be accessed; must be non-negative
|
||||
* and no larger than {@code dsts.length - offset}
|
||||
* @param timeout
|
||||
* The timeout, or {@code 0L} for no timeout
|
||||
* The maximum time for the I/O operation to complete
|
||||
* @param unit
|
||||
* The time unit of the {@code timeout} argument
|
||||
* @param attachment
|
||||
@ -483,8 +483,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* If the pre-conditions for the {@code offset} and {@code length}
|
||||
* parameter aren't met
|
||||
* @throws IllegalArgumentException
|
||||
* If the {@code timeout} parameter is negative, or a buffer is
|
||||
* read-only
|
||||
* If the buffer is read-only
|
||||
* @throws ReadPendingException
|
||||
* If a read operation is already in progress on this channel
|
||||
* @throws NotYetConnectedException
|
||||
@ -524,7 +523,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* @param src
|
||||
* The buffer from which bytes are to be retrieved
|
||||
* @param timeout
|
||||
* The timeout, or {@code 0L} for no timeout
|
||||
* The maximum time for the I/O operation to complete
|
||||
* @param unit
|
||||
* The time unit of the {@code timeout} argument
|
||||
* @param attachment
|
||||
@ -532,8 +531,6 @@ public abstract class AsynchronousSocketChannel
|
||||
* @param handler
|
||||
* The handler for consuming the result
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the {@code timeout} parameter is negative
|
||||
* @throws WritePendingException
|
||||
* If a write operation is already in progress on this channel
|
||||
* @throws NotYetConnectedException
|
||||
@ -623,7 +620,7 @@ public abstract class AsynchronousSocketChannel
|
||||
* The maximum number of buffers to be accessed; must be non-negative
|
||||
* and no larger than {@code srcs.length - offset}
|
||||
* @param timeout
|
||||
* The timeout, or {@code 0L} for no timeout
|
||||
* The maximum time for the I/O operation to complete
|
||||
* @param unit
|
||||
* The time unit of the {@code timeout} argument
|
||||
* @param attachment
|
||||
@ -634,8 +631,6 @@ public abstract class AsynchronousSocketChannel
|
||||
* @throws IndexOutOfBoundsException
|
||||
* If the pre-conditions for the {@code offset} and {@code length}
|
||||
* parameter aren't met
|
||||
* @throws IllegalArgumentException
|
||||
* If the {@code timeout} parameter is negative
|
||||
* @throws WritePendingException
|
||||
* If a write operation is already in progress on this channel
|
||||
* @throws NotYetConnectedException
|
||||
|
@ -235,8 +235,6 @@ abstract class AsynchronousSocketChannelImpl
|
||||
|
||||
if (remoteAddress == null)
|
||||
throw new NotYetConnectedException();
|
||||
if (timeout < 0L)
|
||||
throw new IllegalArgumentException("Negative timeout");
|
||||
|
||||
boolean hasSpaceToRead = isScatteringRead || dst.hasRemaining();
|
||||
boolean shutdown = false;
|
||||
@ -342,8 +340,6 @@ abstract class AsynchronousSocketChannelImpl
|
||||
if (isOpen()) {
|
||||
if (remoteAddress == null)
|
||||
throw new NotYetConnectedException();
|
||||
if (timeout < 0L)
|
||||
throw new IllegalArgumentException("Negative timeout");
|
||||
// check and update state
|
||||
synchronized (writeLock) {
|
||||
if (writeKilled)
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4607272 6842687
|
||||
* @bug 4607272 6842687 6878369
|
||||
* @summary Unit test for AsynchronousSocketChannel
|
||||
* @run main/timeout=600 Basic
|
||||
*/
|
||||
@ -712,52 +712,57 @@ public class Basic {
|
||||
}
|
||||
|
||||
static void testTimeout() throws Exception {
|
||||
System.out.println("-- timeouts --");
|
||||
testTimeout(Integer.MIN_VALUE, TimeUnit.SECONDS);
|
||||
testTimeout(-1L, TimeUnit.SECONDS);
|
||||
testTimeout(0L, TimeUnit.SECONDS);
|
||||
testTimeout(2L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
static void testTimeout(final long timeout, final TimeUnit unit) throws Exception {
|
||||
Server server = new Server();
|
||||
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open();
|
||||
ch.connect(server.address()).get();
|
||||
|
||||
System.out.println("-- timeout when reading --");
|
||||
|
||||
ByteBuffer dst = ByteBuffer.allocate(512);
|
||||
|
||||
final AtomicReference<Throwable> readException = new AtomicReference<Throwable>();
|
||||
|
||||
// this read should timeout
|
||||
ch.read(dst, 3, TimeUnit.SECONDS, (Void)null,
|
||||
new CompletionHandler<Integer,Void>()
|
||||
{
|
||||
// this read should timeout if value is > 0
|
||||
ch.read(dst, timeout, unit, null, new CompletionHandler<Integer,Void>() {
|
||||
public void completed(Integer result, Void att) {
|
||||
throw new RuntimeException("Should not complete");
|
||||
readException.set(new RuntimeException("Should not complete"));
|
||||
}
|
||||
public void failed(Throwable exc, Void att) {
|
||||
readException.set(exc);
|
||||
}
|
||||
});
|
||||
// wait for exception
|
||||
while (readException.get() == null) {
|
||||
Thread.sleep(100);
|
||||
if (timeout > 0L) {
|
||||
// wait for exception
|
||||
while (readException.get() == null) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
if (!(readException.get() instanceof InterruptedByTimeoutException))
|
||||
throw new RuntimeException("InterruptedByTimeoutException expected");
|
||||
|
||||
// after a timeout then further reading should throw unspecified runtime exception
|
||||
boolean exceptionThrown = false;
|
||||
try {
|
||||
ch.read(dst);
|
||||
} catch (RuntimeException x) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
if (!exceptionThrown)
|
||||
throw new RuntimeException("RuntimeException expected after timeout.");
|
||||
} else {
|
||||
Thread.sleep(1000);
|
||||
Throwable exc = readException.get();
|
||||
if (exc != null)
|
||||
throw new RuntimeException(exc);
|
||||
}
|
||||
if (!(readException.get() instanceof InterruptedByTimeoutException))
|
||||
throw new RuntimeException("InterruptedByTimeoutException expected");
|
||||
|
||||
// after a timeout then further reading should throw unspecified runtime exception
|
||||
boolean exceptionThrown = false;
|
||||
try {
|
||||
ch.read(dst);
|
||||
} catch (RuntimeException x) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
if (!exceptionThrown)
|
||||
throw new RuntimeException("RuntimeException expected after timeout.");
|
||||
|
||||
|
||||
System.out.println("-- timeout when writing --");
|
||||
|
||||
final AtomicReference<Throwable> writeException = new AtomicReference<Throwable>();
|
||||
|
||||
final long timeout = 5;
|
||||
final TimeUnit unit = TimeUnit.SECONDS;
|
||||
|
||||
// write bytes to fill socket buffer
|
||||
ch.write(genBuffer(), timeout, unit, ch,
|
||||
new CompletionHandler<Integer,AsynchronousSocketChannel>()
|
||||
@ -769,24 +774,32 @@ public class Basic {
|
||||
writeException.set(exc);
|
||||
}
|
||||
});
|
||||
if (timeout > 0) {
|
||||
// wait for exception
|
||||
while (writeException.get() == null) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
if (!(writeException.get() instanceof InterruptedByTimeoutException))
|
||||
throw new RuntimeException("InterruptedByTimeoutException expected");
|
||||
|
||||
// wait for exception
|
||||
while (writeException.get() == null) {
|
||||
Thread.sleep(100);
|
||||
// after a timeout then further writing should throw unspecified runtime exception
|
||||
boolean exceptionThrown = false;
|
||||
try {
|
||||
ch.write(genBuffer());
|
||||
} catch (RuntimeException x) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
if (!exceptionThrown)
|
||||
throw new RuntimeException("RuntimeException expected after timeout.");
|
||||
} else {
|
||||
Thread.sleep(1000);
|
||||
Throwable exc = writeException.get();
|
||||
if (exc != null)
|
||||
throw new RuntimeException(exc);
|
||||
}
|
||||
if (!(writeException.get() instanceof InterruptedByTimeoutException))
|
||||
throw new RuntimeException("InterruptedByTimeoutException expected");
|
||||
|
||||
// after a timeout then further writing should throw unspecified runtime exception
|
||||
exceptionThrown = false;
|
||||
try {
|
||||
ch.write(genBuffer());
|
||||
} catch (RuntimeException x) {
|
||||
exceptionThrown = true;
|
||||
}
|
||||
if (!exceptionThrown)
|
||||
throw new RuntimeException("RuntimeException expected after timeout.");
|
||||
|
||||
// clean-up
|
||||
server.accept().close();
|
||||
ch.close();
|
||||
server.close();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user