non-blocking channel Infinite loop in java.util.Scanner (original) (raw)
Rémi Forax forax at univ-mlv.fr
Tue Jun 5 10:00:36 UTC 2012
- Previous message: hg: jdk8/tl/jdk: 7172701: KDC tests cleanup
- Next message: non-blocking channel Infinite loop in java.util.Scanner
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
One of my student find a bug in the implementation of Scanner, that allows you to use a non blocking channel as input of a Scanner.
The Scanner uses Channels.newReader() to create a Reader from a channel which itself create a StreamDecoder.
In that case, StreamDecoder.impReader() goes into an infinite loop because impReader() calls readBytes() that does nothing if channel.read() returns zero.
The javadoc of Channels.newReader() clearly states that it should throw a IllegalBlockingModeException but there is no code that checks that.
I think a way to solve the problem is to insert a code that check the blocking state in Channels.newWriter().
if (ch instanceof SelectableChannel) { SelectableChannel sc = (SelectableChannel)ch; if (!sc.isBlocking()) throw new IllegalBlockingModeException(); } }
and to document the exception in the constructor of Scanner that takes a channel.
If someone provide me a bug id, it will provide a patch :)
cheers, Rémi
PS: The code below is a simple test to reproduce the infinite loop.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Scanner;
public class Main { public static void main(String[] args) throws IOException { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(2332));
new Thread(new Runnable() {
@Override
public void run() {
try {
SocketChannel channel = SocketChannel.open(new
InetSocketAddress("localhost", 2332)); do { channel.write(ByteBuffer.wrap(new byte[] {'A'})); Thread.sleep(1000); } while(true); } catch (IOException | InterruptedException e) { throw new AssertionError(e); }
}
}).start();
SocketChannel socketChannel = serverSocketChannel.accept();
socketChannel.configureBlocking(false);
Scanner scanner = new Scanner(socketChannel);
while(scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
} }
- Previous message: hg: jdk8/tl/jdk: 7172701: KDC tests cleanup
- Next message: non-blocking channel Infinite loop in java.util.Scanner
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]