diff -Naur jruby_3536/src/org/jruby/RubyIO.java jruby/src/org/jruby/RubyIO.java
--- jruby_3536/src/org/jruby/RubyIO.java	2007-04-23 10:49:26.000000000 -0400
+++ jruby/src/org/jruby/RubyIO.java	2007-04-23 13:59:18.000000000 -0400
@@ -47,6 +47,8 @@
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 
 import org.jruby.runtime.Arity;
 import org.jruby.runtime.Block;
@@ -398,6 +400,14 @@
             return null;
         }
     }
+    
+    public boolean hasPendingBuffered() {
+        if (handler!=null) {
+            return handler.hasPendingBuffered();
+        } else {
+            return false;
+        }
+    }
 
     public IRubyObject reopen(IRubyObject[] args) {
     	if (args.length < 1) {
@@ -1283,13 +1293,13 @@
        return runtime.getNil();
    }
    
-   private static void registerSelect(Selector selector, IRubyObject obj, int ops) throws IOException {
+   private static RubyIO registerSelect(Selector selector, IRubyObject obj, int ops) throws IOException {
        RubyIO ioObj;
        
        if(!(obj instanceof RubyIO)) {
            // invoke to_io
            if(!obj.respondsTo("to_io")) {
-               return;
+               return null;
            }
            ioObj = (RubyIO) obj.callMethod(obj.getRuntime().getCurrentContext(), "to_io");
        } else {
@@ -1298,7 +1308,7 @@
        
        Channel channel = ioObj.getChannel();
        if(channel == null || !(channel instanceof SelectableChannel)) {
-           return;
+           return null;
        }
        
        ((SelectableChannel) channel).configureBlocking(false);
@@ -1310,6 +1320,7 @@
        } else {
            key.interestOps(key.interestOps()|real_ops);
        }
+       return ioObj;
    }
    
    public static IRubyObject select(IRubyObject recv, IRubyObject[] args) {
@@ -1320,6 +1331,8 @@
        try {
            boolean atLeastOneDescriptor = false;
            
+	   Set pending = new HashSet();
+
            Selector selector = Selector.open();
            if (!args[0].isNil()) {
                atLeastOneDescriptor = true;
@@ -1327,7 +1340,10 @@
                // read
                for (Iterator i = ((RubyArray) args[0]).getList().iterator(); i.hasNext(); ) {
                    IRubyObject obj = (IRubyObject) i.next();
-                   registerSelect(selector, obj, SelectionKey.OP_READ|SelectionKey.OP_ACCEPT);
+                   RubyIO ioObj = registerSelect(selector, obj, SelectionKey.OP_READ|SelectionKey.OP_ACCEPT);
+                   if (ioObj!=null && ioObj.hasPendingBuffered()) {
+                        pending.add(obj);
+                   }
                }
            }
            if (args.length > 1 && !args[1].isNil()) {
@@ -1360,10 +1376,19 @@
                return runtime.getNil();
            }
            
-           if(args.length > 3) {
-               selector.select(timeout);
+           // Erk! Convoluted!
+           if (pending.isEmpty()) {
+               if(args.length > 3) {
+                   if (timeout==0) {
+                       selector.selectNow();
+                   } else {
+                       selector.select(timeout);
+                   }
+               } else {
+                   selector.select();
+               }
            } else {
-               selector.select();
+               selector.selectNow();
            }
            
            List r = new ArrayList();
@@ -1374,12 +1399,14 @@
                if ((key.interestOps() & key.readyOps()
                        & (SelectionKey.OP_READ|SelectionKey.OP_ACCEPT|SelectionKey.OP_CONNECT)) != 0) {
                    r.add(key.attachment());
+		   pending.remove(key.attachment());
                }
                if ((key.interestOps() & key.readyOps() & (SelectionKey.OP_WRITE)) != 0) {
                    w.add(key.attachment());
                }
            }
-           
+           r.addAll(pending);
+
            // make all sockets blocking as configured again
            for (Iterator i = selector.keys().iterator(); i.hasNext(); ) {
                SelectionKey key = (SelectionKey) i.next();
diff -Naur jruby_3536/src/org/jruby/util/IOHandler.java jruby/src/org/jruby/util/IOHandler.java
--- jruby_3536/src/org/jruby/util/IOHandler.java	2007-04-23 10:49:10.000000000 -0400
+++ jruby/src/org/jruby/util/IOHandler.java	2007-04-23 13:46:19.000000000 -0400
@@ -138,6 +138,10 @@
         
         resetByModes(subsetModes);
     }
+   
+    public boolean hasPendingBuffered() {
+        return false;
+    }
 
     public abstract ByteList gets(ByteList separatorString) throws IOException, BadDescriptorException, EOFException;
     public abstract ByteList getsEntireStream() throws IOException, BadDescriptorException, EOFException;
diff -Naur jruby_3536/src/org/jruby/util/IOHandlerNio.java jruby/src/org/jruby/util/IOHandlerNio.java
--- jruby_3536/src/org/jruby/util/IOHandlerNio.java	2007-04-23 10:49:10.000000000 -0400
+++ jruby/src/org/jruby/util/IOHandlerNio.java	2007-04-23 13:48:57.000000000 -0400
@@ -177,16 +177,20 @@
 
     int ungotc = -1;
 
+    public boolean hasPendingBuffered() {
+        return ungotc >=0 || (bufferedIO && inBuffer.remaining()>0);
+    }
+
     private ByteList consumeInBuffer(int length) {
         int offset = 0;
-        if (ungotc > 0) {
+        if (ungotc >= 0) {
             length--;
             offset = 1;
         }
         length = inBuffer.remaining() < length ? inBuffer.remaining() : length;
         byte[] ret = new byte[length + offset];
         inBuffer.get(ret, offset, length);
-        if (ungotc > 0) {
+        if (ungotc >= 0) {
             ret[0] = (byte) (ungotc & 0xff);
             ungotc = -1;
         }
@@ -354,7 +358,7 @@
         checkReadable();
         setupBufferedIO();
 
-        if (ungotc > 0) {
+        if (ungotc >= 0) {
             int i = ungotc;
             ungotc = -1;
             return i;
@@ -400,7 +404,7 @@
         setupBufferedIO();
         checkReadable();
 
-        if (ungotc > 0) {
+        if (ungotc >= 0) {
 	    return false;
 	}
         if (inBuffer.hasRemaining()) {
@@ -426,7 +430,7 @@
     public long pos() throws PipeException, IOException {
         if (channel instanceof FileChannel) {
             if (bufferedIO) {
-                return ((FileChannel) channel).position() - (inBuffer.remaining() + (ungotc > 0 ? 1 : 0));
+                return ((FileChannel) channel).position() - (inBuffer.remaining() + (ungotc >= 0 ? 1 : 0));
             } else {
                 return ((FileChannel) channel).position();
             }
