JDK-4750978 : (process) Runtime.exec/Process.waitFor hang when a new directory is given (lnx)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.4.1
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2002-09-20
  • Updated: 2021-11-09
  • Resolved: 2002-12-17
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
1.4.2 b11Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description

Name: nt126004			Date: 09/20/2002


FULL PRODUCT VERSION :
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)


FULL OPERATING SYSTEM VERSION : RedHat 7.2, kernel 2.4.7-10,
glibc-2.2.4-13


A DESCRIPTION OF THE PROBLEM :
This appears to be specific to Linux.
Repeated calls to Runtime.exec(command,envp,dir) method
eventually cause the JVM to hang. This does not happen with
the Runtime.exec(command) method. Also this does not happen
in J2SDK 1.4.0

Depending on the code used, this may happen when reading
input or error streams from the created process, or during
the exec call itself, or during a Process.waitFor() call.

REGRESSION.  Last worked in version 1.4

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Choose one of the Java programs attached
2. Compile and run. You may need an environment with fairly
fast terminal IO, eg. text console rather than X
3. Output should stop after no more than 5-10 seconds
4. Reinstate the commented out exec call, and comment out
the previous one.
5. Recompile, rerun
6. Output continues (apparently) indefinitely


EXPECTED VERSUS ACTUAL BEHAVIOR :
JVM hangs rather than executing indefinitely.

REPRODUCIBILITY :
This bug can be reproduced always.

ERROR MESSAGES :
here is a thread dump from a hung run -
Full thread dump Java HotSpot(TM) Client VM (1.4.1-b21 mixed mode):

"process reaper" daemon prio=1 tid=0x0x81552e0 nid=0x2067 runnable [4c76e000..4c76e860]
        at java.lang.UNIXProcess.waitForProcessExit(Native Method)
        at java.lang.UNIXProcess.access$1500(UNIXProcess.java:20)
        at java.lang.UNIXProcess$2.run(UNIXProcess.java:127)

"Signal Dispatcher" daemon prio=1 tid=0x0x808d920 nid=0x2011 waiting on condition [0..0]

"Finalizer" daemon prio=1 tid=0x0x8086d68 nid=0x200e in Object.wait() [4c3f2000..4c3f2860]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x441f0490> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
        - locked <0x441f0490> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=1 tid=0x0x8086120 nid=0x200d in Object.wait() [4c371000..4c371860]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x441f0380> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:426)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:113)
        - locked <0x441f0380> (a java.lang.ref.Reference$Lock)

"main" prio=1 tid=0x0x8051e58 nid=0x200a runnable [bfffd000..bfffd5d8]
        at java.io.FileInputStream.readBytes(Native Method)
        at java.io.FileInputStream.read(FileInputStream.java:191)
        at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:222)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:277)
        - locked <0x4425fa20> (a java.io.BufferedInputStream)
        at java.io.FilterInputStream.read(FilterInputStream.java:90)
        at execbust.main(execbust.java:20)

"VM Thread" prio=1 tid=0x0x8082ee0 nid=0x200c runnable 

"VM Periodic Task Thread" prio=1 tid=0x0x808c450 nid=0x200f waiting on condition 
"Suspend Checker Thread" prio=1 tid=0x0x808ceb8 nid=0x2010 runnable 

---------- BEGIN SOURCE ----------
// This example tries reading the input and error streams. JVM hangs while
// reading the input/error streams, in a consistent way
class execbust
{
  public static void main(String args[])
  {
    try {
      File file = new File(".");
      byte iobuf[] = new byte[1024];
      int bytes;
      while (true) {
        InputStream errStream,inStream;
        System.out.print('E');
        Process proc = Runtime.getRuntime().exec("pwd",null,file);
//        Process proc = Runtime.getRuntime().exec("pwd");
        System.out.print('e');
        inStream = proc.getInputStream();
        errStream = proc.getErrorStream();
        while ((bytes = inStream.read(iobuf)) > 0)
          System.out.write(iobuf,0,bytes);
        while ((bytes = errStream.read(iobuf)) > 0)
          System.err.write(iobuf,0,bytes);
        
        System.out.print('W');
        proc.waitFor();
        System.out.print('w');
  
        System.out.print('C');
        errStream.close();
        inStream.close();
        proc.getOutputStream().close();
        System.out.print('c');
      }
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

import java.io.*;

// All streams are just closed after use; no reading/writing. The JVM hangs
// in an unpredicatable way, sometimes in exec(), sometimes in waitFor()
class execbust2
{
  public static void main(String args[])
  {
    try {
      File file = new File(".");
      while (true) {
        System.out.print('E');
        Process proc = Runtime.getRuntime().exec("pwd",null,file);
//        Process proc = Runtime.getRuntime().exec("pwd");
        System.out.print('e');
        
        System.out.print('W');
        proc.waitFor();
        System.out.print('w');
  
        System.out.print('C');
        proc.getOutputStream().close();
        proc.getInputStream().close();
        proc.getErrorStream().close();
        System.out.print('c');
      }
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
None found as yet

Release Regression From : 1.4
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Review ID: 164718) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis-beta FIXED IN: mantis-beta INTEGRATED IN: mantis-b11 mantis-beta
14-06-2004

EVALUATION The root problem is that when a new working directory is specified in an invocation of Runtime.exec the conversion of the pathname string to a char* in the underlying native code is done after forking the child process, which can cause the child process to deadlock with the parent. The fix is to do this conversion before forking the child. The fix is identical to one already applied to the Solaris version of this code (4486978), though the failure mode on Solaris is more catastrophic. -- ###@###.### 2002/11/22
11-10-0188