src/windows/classes/sun/nio/ch/PipeImpl.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.  Oracle designates this

@@ -70,48 +70,56 @@
         implements PrivilegedExceptionAction<Void>
     {
 
         private final SelectorProvider sp;
 
+        private IOException ioe = null;
+
         private Initializer(SelectorProvider sp) {
             this.sp = sp;
         }
 
+        @Override
         public Void run() throws IOException {
+            boolean interrupted = false;
+
             ServerSocketChannel ssc = null;
             SocketChannel sc1 = null;
             SocketChannel sc2 = null;
 
             try {
                 // loopback address
                 InetAddress lb = InetAddress.getByName("127.0.0.1");
                 assert(lb.isLoopbackAddress());
-
-                // bind ServerSocketChannel to a port on the loopback address
+                InetSocketAddress sa = null;
+                for(;;) {
+                    // bind ServerSocketChannel to a port on the loopback
+                    // address
+                    if (ssc == null || !ssc.isOpen()) {
                 ssc = ServerSocketChannel.open();
                 ssc.socket().bind(new InetSocketAddress(lb, 0));
+                        sa = new InetSocketAddress(lb,
+                                ssc.socket().getLocalPort());
+                    }
 
-                // Establish connection (assumes connections are eagerly
+                    // Establish connection (assume connections are eagerly
                 // accepted)
-                InetSocketAddress sa
-                    = new InetSocketAddress(lb, ssc.socket().getLocalPort());
                 sc1 = SocketChannel.open(sa);
-
                 ByteBuffer bb = ByteBuffer.allocate(8);
                 long secret = rnd.nextLong();
                 bb.putLong(secret).flip();
                 sc1.write(bb);
 
                 // Get a connection and verify it is legitimate
-                for (;;) {
                     sc2 = ssc.accept();
                     bb.clear();
                     sc2.read(bb);
                     bb.rewind();
                     if (bb.getLong() == secret)
                         break;
                     sc2.close();
+                    sc1.close();
                 }
 
                 // Create source and sink channels
                 source = new SourceChannelImpl(sp, sc1);
                 sink = new SinkChannelImpl(sp, sc2);

@@ -119,23 +127,112 @@
                 try {
                     if (sc1 != null)
                         sc1.close();
                     if (sc2 != null)
                         sc2.close();
-                } catch (IOException e2) { }
-                IOException x = new IOException("Unable to establish"
-                                                + " loopback connection");
-                x.initCause(e);
-                throw x;
+                } catch (IOException e2) {}
+
+                if (!(e instanceof ClosedByInterruptException))
+                    throw new IOException("Unable to establish loopback"
+                            + " connection", e);
+                interrupted = true;
+                Thread.interrupted();
             } finally {
                 try {
                     if (ssc != null)
                         ssc.close();
-                } catch (IOException e2) { }
+                } catch (IOException e2) {}
             }
+
+            if (interrupted)
+                UninterruptibleConnect();
+
             return null;
         }
+
+        // Use short-lived uninterruptible thread to establish
+        // loopback connections
+        private void UninterruptibleConnect() throws IOException {
+            Thread connector = new Thread("UninterruptibleConnector") {
+                ServerSocketChannel ssc = null;
+                SocketChannel sc1 = null;
+                SocketChannel sc2 = null;
+
+                @Override
+                public void run() {
+                    try {
+                        // loopback address
+                        InetAddress lb = InetAddress.getByName("127.0.0.1");
+                        assert(lb.isLoopbackAddress());
+                        InetSocketAddress sa = null;
+
+                        for (;;) {
+                            // bind ServerSocketChannel to a port on the
+                            // loopback address
+                            if (ssc == null || !ssc.isOpen()) {
+                                ssc = ServerSocketChannel.open();
+                                ssc.socket().bind(new InetSocketAddress(lb, 0));
+                                sa = new InetSocketAddress(lb,
+                                        ssc.socket().getLocalPort());
+                            }
+                            assert(sa != null);
+
+                            // Establish connection (assumes connections are
+                            // eagerly accepted)
+                            sc1 = SocketChannel.open(sa);
+                            ByteBuffer bb = ByteBuffer.allocate(8);
+                            long secret = rnd.nextLong();
+                            bb.putLong(secret).flip();
+                            sc1.write(bb);
+
+                            // Get a connection and verify it is legitimate
+                            sc2 = ssc.accept();
+                            bb.clear();
+                            sc2.read(bb);
+                            bb.rewind();
+                            if (bb.getLong() == secret)
+                                break;
+                            sc2.close();
+                            sc1.close();
+                        }
+
+                        // Create source and sink channels
+                        source = new SourceChannelImpl(sp, sc1);
+                        sink = new SinkChannelImpl(sp, sc2);
+                    } catch (IOException e) {
+                        try {
+                            if (sc1 != null)
+                                sc1.close();
+                            if (sc2 != null)
+                                sc2.close();
+                        } catch (IOException e2) {}
+                        ioe = e;
+                    } finally {
+                        try {
+                            if (ssc != null)
+                                ssc.close();
+                        } catch (IOException e2) {}
+                    }
+                }
+
+                @Override
+                public void interrupt() {}
+            };
+            connector.start();
+            for(;;) {
+                try {
+                    connector.join();
+                    break;
+                } catch (InterruptedException ex) {}
+            }
+
+            Thread.currentThread().interrupt();
+
+            if (ioe != null || source == null || sink == null)
+                throw new IOException("Unable to establish loopback connection",
+                        ioe);
+        }
     }
 
     PipeImpl(final SelectorProvider sp) throws IOException {
         try {
             AccessController.doPrivileged(new Initializer(sp));