This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[PATCH]: Channels and IllegalBlockingModeException
- From: Mohan Embar <gnustuff at thisiscool dot com>
- To: Michael Koch <konqueror at gmx dot de>
- Cc: java-patches at gcc dot gnu dot org
- Date: Thu, 29 Jan 2004 20:34:49 -0600
- Subject: [PATCH]: Channels and IllegalBlockingModeException
- Reply-to: gnustuff at thisiscool dot com
Hi Michael,
>> On the other hand, I now have inIOOperation in two places:
>> ServerSocketChannelImpl and SocketChannelImpl. I think I
>> can move this to PlainSocketImpl and avoid the duplication.
>> What do you think? (Remember that SocketChannelImpl and
>> ServerSocketChannelImpl <i>must</i> use PlainSocketImpl
>> and are not allowed to have a custom implementation.)
>
>Sounds like the right way.
This is my official submission of this:
http://gcc.gnu.org/ml/java-patches/2004-q1/msg00367.html
...with the refactoring I mentioned above to put the "in channels
operation" indicator in PlainSocketImpl instead of in both
SocketChannelImpl and ServerSocketChannelImpl.
This passes my tests.
I didn't put " (" in any new code I wrote, but I also didn't
change it in old code which I simply indented which shows
up as new code in the diff.
I did and tested this against the trunk and I'm okay with it.
Can you look at this one more time?
-- Mohan
http://www.thisiscool.com/
http://www.animalsong.org/
ChangeLog
2004-01-29 Mohan Embar <gnustuff@thisiscool.com>
* gnu/java/net/PlainSocketImpl.java
(inChannelOperation): New field.
(isInChannelOperation): New accessor.
(setInChannelOperation): New modifier.
* gnu/java/nio/ServerSocketChannelImpl.java
(accept): Set and reset our server socket's PlainSocketImpl's
"in channel operation" indicator before and after delegating
the accept to our server socket.
* gnu/java/nio/SocketChannelImpl.java
(connect): Set and reset our socket's PlainSocketImpl's "in channel
operation" indicator before and after delegating the operation to
our socket.
(read): Likewise.
(write): Likewise.
* java/net/ServerSocket.java (implAccept): Don't throw an
IllegalBlockingModeException if we have a non-blocking
channel which initiated this accept operation.
* java/net/Socket.java (connect): Don't throw an
IllegalBlockingModeException if we have a non-blocking
channel which initiated this connect operation.
* java/nio/channels/spi/AbstractSelectableChannel.java
(configureBlocking): Only call implConfigureBlocking() if
the desired blocking mode is different from our current one.
Index: gnu/java/net/PlainSocketImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/net/PlainSocketImpl.java,v
retrieving revision 1.4
diff -u -2 -r1.4 PlainSocketImpl.java
--- gnu/java/net/PlainSocketImpl.java 21 Oct 2003 12:29:43 -0000 1.4
+++ gnu/java/net/PlainSocketImpl.java 30 Jan 2004 01:38:19 -0000
@@ -121,4 +121,31 @@
/**
+ * Indicates whether a channel initiated whatever operation
+ * is being invoked on this socket.
+ */
+ private boolean inChannelOperation;
+
+ /**
+ * Indicates whether we should ignore whether any associated
+ * channel is set to non-blocking mode. Certain operations
+ * throw an <code>IllegalBlockingModeException</code> if the
+ * associated channel is in non-blocking mode, <i>except</i>
+ * if the operation is invoked by the channel itself.
+ */
+ public final boolean isInChannelOperation()
+ {
+ return inChannelOperation;
+ }
+
+ /**
+ * Sets our indicator of whether an I/O operation is being
+ * initiated by a channel.
+ */
+ public final void setInChannelOperation(boolean b)
+ {
+ inChannelOperation = b;
+ }
+
+ /**
* Default do nothing constructor
*/
Index: gnu/java/nio/ServerSocketChannelImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/nio/ServerSocketChannelImpl.java,v
retrieving revision 1.11
diff -u -2 -r1.11 ServerSocketChannelImpl.java
--- gnu/java/nio/ServerSocketChannelImpl.java 7 Jan 2004 16:51:49 -0000 1.11
+++ gnu/java/nio/ServerSocketChannelImpl.java 30 Jan 2004 01:38:20 -0000
@@ -70,5 +70,5 @@
return serverSocket.getPlainSocketImpl().getNativeFD();
}
-
+
public void finalizer()
{
@@ -108,4 +108,9 @@
try
{
+ begin();
+ serverSocket.getPlainSocketImpl().setInChannelOperation(true);
+ // indicate that a channel is initiating the accept operation
+ // so that the socket ignores the fact that we might be in
+ // non-blocking mode.
NIOSocket socket = (NIOSocket) serverSocket.accept();
completed = true;
@@ -118,4 +123,5 @@
finally
{
+ serverSocket.getPlainSocketImpl().setInChannelOperation(false);
end (completed);
}
Index: gnu/java/nio/SocketChannelImpl.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/java/nio/SocketChannelImpl.java,v
retrieving revision 1.15
diff -u -2 -r1.15 SocketChannelImpl.java
--- gnu/java/nio/SocketChannelImpl.java 7 Jan 2004 16:51:49 -0000 1.15
+++ gnu/java/nio/SocketChannelImpl.java 30 Jan 2004 01:38:20 -0000
@@ -137,21 +137,33 @@
throw new UnresolvedAddressException();
- if (isBlocking())
- {
- // Do blocking connect.
- socket.connect (remote);
- return true;
- }
-
- // Do non-blocking connect.
try
{
- socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
- return true;
+ socket.getPlainSocketImpl().setInChannelOperation(true);
+ // indicate that a channel is initiating the accept operation
+ // so that the socket ignores the fact that we might be in
+ // non-blocking mode.
+
+ if (isBlocking())
+ {
+ // Do blocking connect.
+ socket.connect (remote);
+ return true;
+ }
+
+ // Do non-blocking connect.
+ try
+ {
+ socket.connect (remote, NIOConstants.DEFAULT_TIMEOUT);
+ return true;
+ }
+ catch (SocketTimeoutException e)
+ {
+ connectionPending = true;
+ return false;
+ }
}
- catch (SocketTimeoutException e)
+ finally
{
- connectionPending = true;
- return false;
+ socket.getPlainSocketImpl().setInChannelOperation(false);
}
}
@@ -239,4 +251,5 @@
{
begin();
+ socket.getPlainSocketImpl().setInChannelOperation(true);
readBytes = input.read (data, offset, len);
completed = true;
@@ -245,4 +258,5 @@
{
end (completed);
+ socket.getPlainSocketImpl().setInChannelOperation(false);
}
@@ -302,5 +316,18 @@
OutputStream output = socket.getOutputStream();
- output.write (data, offset, len);
+ boolean completed = false;
+
+ try
+ {
+ begin();
+ socket.getPlainSocketImpl().setInChannelOperation(true);
+ output.write (data, offset, len);
+ completed = true;
+ }
+ finally
+ {
+ end (completed);
+ socket.getPlainSocketImpl().setInChannelOperation(false);
+ }
if (src.hasArray())
Index: java/net/ServerSocket.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/ServerSocket.java,v
retrieving revision 1.34
diff -u -2 -r1.34 ServerSocket.java
--- java/net/ServerSocket.java 7 Jan 2004 16:37:45 -0000 1.34
+++ java/net/ServerSocket.java 30 Jan 2004 01:38:23 -0000
@@ -346,7 +346,12 @@
throw new SocketException("ServerSocket is closed");
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
if (getChannel() != null
- && !getChannel().isBlocking())
- throw new IllegalBlockingModeException();
+ && !getChannel().isBlocking ()
+ && !((PlainSocketImpl) getImpl()).isInChannelOperation())
+ throw new IllegalBlockingModeException ();
impl.accept(socket.getImpl());
Index: java/net/Socket.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/net/Socket.java,v
retrieving revision 1.33
diff -u -2 -r1.33 Socket.java
--- java/net/Socket.java 9 Dec 2003 15:39:23 -0000 1.33
+++ java/net/Socket.java 30 Jan 2004 01:38:24 -0000
@@ -421,6 +421,11 @@
throw new IllegalArgumentException("unsupported address type");
+ // The Sun spec says that if we have an associated channel and
+ // it is in non-blocking mode, we throw an IllegalBlockingModeException.
+ // However, in our implementation if the channel itself initiated this
+ // operation, then we must honor it regardless of its blocking mode.
if (getChannel() != null
- && !getChannel().isBlocking ())
+ && !getChannel().isBlocking ()
+ && !((PlainSocketImpl) getImpl()).isInChannelOperation())
throw new IllegalBlockingModeException ();
Index: java/nio/channels/spi/AbstractSelectableChannel.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/nio/channels/spi/AbstractSelectableChannel.java,v
retrieving revision 1.7
diff -u -2 -r1.7 AbstractSelectableChannel.java
--- java/nio/channels/spi/AbstractSelectableChannel.java 7 Jan 2004 16:51:49 -0000 1.7
+++ java/nio/channels/spi/AbstractSelectableChannel.java 30 Jan 2004 01:38:24 -0000
@@ -81,6 +81,9 @@
synchronized (blockingLock())
{
- implConfigureBlocking(blocking);
- this.blocking = blocking;
+ if (this.blocking != blocking)
+ {
+ implConfigureBlocking(blocking);
+ this.blocking = blocking;
+ }
}