--- old/src/windows/classes/sun/nio/ch/PipeImpl.java 2012-12-19 22:03:20.252405761 -0800 +++ new/src/windows/classes/sun/nio/ch/PipeImpl.java 2012-12-19 22:03:19.744405776 -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,67 +72,99 @@ private final SelectorProvider sp; + private IOException ioe = null; + private Initializer(SelectorProvider sp) { this.sp = sp; } + @Override public Void run() throws IOException { - 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 - 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 (;;) { - sc2 = ssc.accept(); - bb.clear(); - sc2.read(bb); - bb.rewind(); - if (bb.getLong() == secret) + LoopbackConnector connector = new LoopbackConnector(); + connector.run(); + if (ioe instanceof ClosedByInterruptException) { + ioe = null; + Thread connThread = new Thread(connector) { + @Override + public void interrupt() {} + }; + connThread.start(); + for(;;) { + try { + connThread.join(); break; - sc2.close(); + } catch (InterruptedException ex) {} } + Thread.currentThread().interrupt(); + } + + if (ioe != null || source == null || sink == null) + throw new IOException("Unable to establish loopback connection", + ioe); + + return null; + } + + private class LoopbackConnector implements Runnable { + + @Override + public void run() { + ServerSocketChannel ssc = null; + SocketChannel sc1 = null; + SocketChannel sc2 = null; - // 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) + // 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); + + // 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(); - } catch (IOException e2) { } - IOException x = new IOException("Unable to establish" - + " loopback connection"); - x.initCause(e); - throw x; - } finally { - try { - if (ssc != null) - ssc.close(); - } catch (IOException e2) { } + 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) {} + } } - return null; } } @@ -144,7 +176,6 @@ } } - public SourceChannel source() { return source; } --- /dev/null 2012-12-19 21:43:12.587152292 -0800 +++ new/test/java/nio/channels/Pipe/PipeInterrupt.java 2012-12-19 22:03:20.580405751 -0800 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8002306 + * @summary Ensure that a Pipe can open even if its thread has already + * been interrupted. + * @author Dan Xu + */ + +import java.io.IOException; +import java.nio.channels.*; + + +public class PipeInterrupt { + + private Pipe testPipe = null; + private IOException ie = null; + + public static void main(String... args) throws IOException { + PipeInterrupt instance = new PipeInterrupt(); + instance.test(); + instance.close(); + } + + public void test() throws IOException { + Thread tester = new Thread("PipeTester") { + + @Override + public void run() { + while (!this.isInterrupted()); + try { + testPipe = Pipe.open(); + } catch (IOException e) { + ie = e; + } + } + }; + tester.start(); + tester.interrupt(); + while(tester.isAlive()); + + if (ie != null) + throw new IOException("Fail to open a pipe", ie); + } + + public void close() throws IOException { + if (testPipe != null) { + testPipe.sink().close(); + testPipe.source().close(); + } + } +}