JDK-6907260 : BindException when using java.nio.channels.Pipe on Windows
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 6u17
  • Priority: P4
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-12-04
  • Updated: 2011-02-16
  • Resolved: 2009-12-04
Description
FULL PRODUCT VERSION :
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04)
Java HotSpot(TM) Client VM (build 14.3-b01, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Using the java.nio.channels.Pipe class on a Windows system can result in a BindException being thrown.  This is very odd , as one would not expect an internal pipe implementation to have any need for sockets.

This problem does not seem to occur on Linux.



STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the supplied test program on a Windows platform.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
  Program should run indefinitely (as it does on Linux systems, for example).
ACTUAL -
  Program aborts because of a BindException after a few thousand iterations.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.io.IOException: Unable to establish loopback connection
        at sun.nio.ch.PipeImpl$Initializer.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at sun.nio.ch.PipeImpl.<init>(Unknown Source)
        at sun.nio.ch.SelectorProviderImpl.openPipe(Unknown Source)
        at java.nio.channels.Pipe.open(Unknown Source)
        at Test.main(Test.java:17)
Caused by: java.net.BindException: Address already in use: connect
        at sun.nio.ch.Net.connect(Native Method)
        at sun.nio.ch.SocketChannelImpl.connect(Unknown Source)
        at java.nio.channels.SocketChannel.open(Unknown Source)
        ... 6 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.Pipe;

public class Test {
  public static void main(String[] args) throws IOException {

    long count = 0;
    while (true) {
      Pipe pipe = Pipe.open();
      InputStream inputStream  = Channels.newInputStream(pipe.source());
      OutputStream outputStream = Channels.newOutputStream(pipe.sink());

      outputStream.write('x');
      inputStream.read();

      outputStream.close();
      inputStream.close();

      System.out.println(++count);
    }
  }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
No easy workaround -- I ended up implementing my own pipe class.

One could try using PipedOutputStream/PipedInputStream, but these classes are flawed (by design!) and do not allow multiple threads to read/write to them (i.e., once you write to a PipedOutputStream from a particular thread, you can't write to it from any other thread).

Comments
EVALUATION Windows doesn't support socketpairs so Pipe is implemented as a loopback connection on that platform. The "client" side of that connection doesn't explicitly bind and so it allocated an ephemeral port in the range 1024-5000. This limits the number of Pipes but the submitter can incresae the MaxUserPort entry in registry if he/she really needs thounsands of Pipes. Also note that when the sink/source are closed then the connection goes into the TCP TIME_WAIT state for a timeout period known as 2*MSL. If the submitter is creating Pipes at a very high rate then it is possible to run out of connections. Reducing the value of the TcpTimedWaitDelay registry setting should help with this.
04-12-2009