non-blocking channel Infinite loop in java.util.Scanner

Rémi Forax forax at
Tue Jun 5 23:12:16 UTC 2012

On 06/05/2012 12:40 PM, Alan Bateman wrote:
> On 05/06/2012 11:00, Rémi Forax wrote:
>> 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 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();
>>             }
>>    }
> This could be fixed in Channels.newReader or in StreamDecoder, the 
> former would be consistent with Channels.newWriter. I guess you know 
> this already, but you will need to synchronize on the selectable 
> channel's blockingLock to ensure that the blocking mode doesn't change.
> I've created a bug for this:
> 7174305: (ch) Channels.newReader doesn't throw IllegalBlockingMode if 
> channel is configured non-blocking
> -Alan.

Thanks Alan,

I can't ensure that the blocking mode will not change by synchronizing on
the channel's blockingLock because I will have to take the lock
before creating the reader and releasing it when the reader is closed.

An easier solution is to throw an IllegalBlockingModeException
if the returns 0, in that case I think I don't have to 
even check the configured mode
(the question is what to do if the configured mode is changed by another 
thread between the call to read()
and the call to isBlocking()).

and BTW isBlocking() already takes the lock, may be the doc of 
isBlocking() should more clear about that.


More information about the core-libs-dev mailing list