From b6b4b5086c410d7fdf637a34cbda74c204cc9a41 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 24 Nov 2010 09:51:31 +0000 Subject: [PATCH] 6878369: (ch) AsynchronousSocketChannel read/write methods that specify timeouts should not throw IAE Reviewed-by: forax --- .../channels/AsynchronousSocketChannel.java | 21 ++-- .../nio/ch/AsynchronousSocketChannelImpl.java | 4 - .../AsynchronousSocketChannel/Basic.java | 101 ++++++++++-------- 3 files changed, 65 insertions(+), 61 deletions(-) diff --git a/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java index d37bd2efc46..6d04f4f52a2 100644 --- a/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java +++ b/jdk/src/share/classes/java/nio/channels/AsynchronousSocketChannel.java @@ -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 diff --git a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 2e06969253c..047bb61e865 100644 --- a/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -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) diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index e8f23f46866..b38e34efbc0 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -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 readException = new AtomicReference(); - // this read should timeout - ch.read(dst, 3, TimeUnit.SECONDS, (Void)null, - new CompletionHandler() - { + // this read should timeout if value is > 0 + ch.read(dst, timeout, unit, null, new CompletionHandler() { 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 writeException = new AtomicReference(); - final long timeout = 5; - final TimeUnit unit = TimeUnit.SECONDS; - // write bytes to fill socket buffer ch.write(genBuffer(), timeout, unit, ch, new CompletionHandler() @@ -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(); }