Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4067080

java.lang.Runtime.exec: available on stdin returns incorrect count (win32)

XMLWordPrintable

    • 1.2alpha2
    • sparc
    • solaris_2.5
    • Not verified

      Calling System.in.available() fails in win32 if the current JVM process was
      created by calling Runtime.exec() from a different JVM process. It throws an
      IOException (with no detail message).

      This can be demonstrated by compiling and running the attached test case.
      Executing the WriteToChild class will exec another JVM to run the DumpIn class,
      and then it will write some bytes to that process and then shut down. The
      DumpIn class calls available on System.in as well as reading the bytes. All
      output and errors are redirected to a file names "dump.out" so that it can be
      read after the text case is run.

      Doing this with the current JDK 1.2 (or any earlier version, AFAIK) for win32:

      C:\test\exec> java WriteToChild

      will just create a dump.out file that shows the stack trace of the IOException
      from calling available (i.e., the bug). "dump.out" should contain the same
      output that is correctly generated when running the following:

      C:\test\exec> java WriteOut | java DumpIn

      which shows the bytes correctly received.


      The problem is in the win32 implementation of sysAvailable() etc. in the file
      "src/win32/javavm/runtime/sys_api_md.c". It is called with a fd, and if the
      fd is not a regular seekable file in the FS, it calls either stdinAvailable (if
      fd == 0) or nonSeekAvailable (otherwise) to find out about bytes pending on
      special files like pipes, etc.

      These two different functions are required because a different Win32 API
      must be used depending on what kind of windows file handle corresponds to
      the "special" fd. nonSeekAvailable() calls PeekNamedPipe() for handles to
      "pipes", and stdinAvailable() calls WaitForSingleObject() for a handle that
      corresponds to "console input".

      In the usual case, the correct API is used, because the handle for fd==0
      is usually the "console input" if it's not a regular file, and not for other
      fds. But in the "WriteToChild" test case above, that is apparently not true:
      The fd is zero, so stdinAvailable is called. WaitForSingleObject() returns
      the constant WAIT_FAILED and an error condition indicating that the handle was
      "invalid", although that return value just falls to the "default:" case in the
      switch, and FALSE is returned, resulting in the eventual IOException being
      thrown. The documentation for WaitForSingleObject() mentions that its use for
      files or pipes can work "in some circumstances" but "this purpose is
      discouraged".

      The right thing to do would be to call PeekNamedPipe() for this type of handle.
      But PeekNamedPipe() doesn't seem work for "console input" handles, and I'm not
      sure of a better way of determining which API to call ahead of time. So the
      arguably crude but working fix I have is to special case the WAIT_FAILED
      return from WaitForSingleObject() and given PeekNamedPipe() a shot (by calling
      nonSeekAvailable()). See the "suggested fix" for more details.

            mr Mark Reinhold
            peterjones Peter Jones (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: