--- old/src/windows/classes/sun/nio/ch/PipeImpl.java 2012-12-17 15:59:00.767511567 -0800 +++ new/src/windows/classes/sun/nio/ch/PipeImpl.java 2012-12-17 15:59:00.611511572 -0800 @@ -1,5 +1,5 @@ /* - * 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 @@ -72,11 +72,16 @@ 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; @@ -85,24 +90,26 @@ // 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()); + } + + // Establish connection (assume connections are eagerly + // accepted) + sc1 = SocketChannel.open(sa); + ByteBuffer bb = ByteBuffer.allocate(8); + long secret = rnd.nextLong(); + bb.putLong(secret).flip(); + sc1.write(bb); - // bind ServerSocketChannel to a port on the loopback address - ssc = ServerSocketChannel.open(); - ssc.socket().bind(new InetSocketAddress(lb, 0)); - - // Establish connection (assumes 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 (;;) { + // Get a connection and verify it is legitimate sc2 = ssc.accept(); bb.clear(); sc2.read(bb); @@ -110,6 +117,7 @@ if (bb.getLong() == secret) break; sc2.close(); + sc1.close(); } // Create source and sink channels @@ -121,19 +129,108 @@ 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 {