JDK-4763362 : (process) Process.waitFor/exitStatus sometime return incorrect status (lnx)
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.4.1,1.4.2
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2002-10-15
  • Updated: 2002-12-17
  • 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
Duplicate :  
Relates :  
Relates :  
Description

Name: rmT116609			Date: 10/15/2002


FULL PRODUCT VERSION :
java version "1.4.1"
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 : Linux Red Hat 7.3 (2.4 kernel)


A DESCRIPTION OF THE PROBLEM :
The Process object will not always return the correct exitStatus when running on Linux Red Hat v7.3. Other UNIX OSes seem to work fine.


The following code demonstrates the problem:


public class foo {
 public static void main(String args[]) {
  while(true) {
   try {
    Runtime runtime = Runtime.getRuntime();
    Process p = runtime.exec("/bin/false");
    p.waitFor();
    System.out.println("Exit status: " +  p.exitValue() );
   }catch(Exception e) {}
  }
 }
}



This code should always return 1, but the following output
shows what happens:


$ java foo
Exit status: 1
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 1
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 0
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
Exit status: 1
$


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. run the enclosed program


EXPECTED VERSUS ACTUAL BEHAVIOR :
if exitStatus of zero is printed, that's bad


REPRODUCIBILITY :
This bug can be reproduced often.

---------- BEGIN SOURCE ----------
public class foo {
 public static void main(String args[]) {
  while(true) {
   try {
    Runtime runtime = Runtime.getRuntime();
    Process p = runtime.exec("/bin/false");
    p.waitFor();
    System.out.println("Exit status: " +  p.exitValue() );
   }catch(Exception e) {}
  }
 }
}


---------- END SOURCE ----------

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: 165615) 
======================================================================


###@###.### 2002-12-09

Same bug has been reported by a CAP member:

J2SE Version (please include all output from java -version flag):
  J2SDK 1.4.1_01 and J2SDK 1.4.2 cap build 08

  Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
  Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2-beta-b08)

Does this problem occur on J2SE 1.3 or 1.4?
  No.

  Not reproducable with JDK 1.3.1 and J2SDK 1.4.0:

  Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_06-b01)
  Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_03-b04)

Operating System Configuration Information (be specific):
  Redhat Linux 8.0 with all errata up to Dec. 08 2002. Other platforms 
  untested so far.

Hardware Configuration Information (be specific):
  Athlon 1.2GHz, 512MB RAM, Geforce graphics adapter.


Bug Description:
  Process.waitFor() and Process.exitValue() incorrectly return 0 sometimes 
  (non-determistic) even if the exit value of the executed process is 
  always non-zero.

Steps to Reproduce (be specific):
  Run the attached program(ExitTest.java) on J2SDK 1.4.1 on J2SDK 1.4.2 
  build08 and observe the output. The attached program starts "/bin/mv" 
  without arguments 1000 times (sequentially) and checks the return code. 
  It reports how many times zero was incorrectly returned as the exit value.

Test program:(ExitTest.java)

  public class ExitTest
  {
	public static void main(String[] args) throws Throwable
	{
		int wrongExitCodes = 0;
		for (int i = 0; i < 1000; i++)
		{
			Process p = Runtime.getRuntime().exec("/bin/mv");
			int exitCode = p.waitFor();
			exitCode = p.exitValue();
			if (exitCode == 0)
				wrongExitCodes++;
		}
		System.out.println("wrong exit code count: "+wrongExitCodes);
	}
  }

Test result:

  Sample output with J2SDK 1.4.1_01 (WRONG):

  wrong exit code count: 137

  Sample output with J2SDK 1.4.0_03 (CORRECT):

  wrong exit code count: 0

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 HotSpot installs a handler for SIGCHLD which reaps child processes, discarding their exit status. If the timing is right then this signal handler will reap the child before the java.lang.Process reaper thread does, causing an exit value of zero to be reported regardless of the actual value. Whether or not the HotSpot SIGCHLD handler can be overridden or fixed is under investigation. -- ###@###.### 2002/11/26 A few experiments show that in fact the SIGCHLD handler is never invoked for child threads, just for child processes. According to ###@###.###, all threads created on Linux are children of the pthread library's manager thread, and SIGCHLD signals for threads are delivered to the manager thread only. This bug will be fixed by changing the Linux process code to install its own trivial SIGCHLD handler, overriding the HotSpot handler. A P4 cleanup bug (4785154) has been filed against the HotSpot runtime system to remove the current SIGCHLD logic since it doesn't serve any real purpose. -- ###@###.### 2002/11/26
11-10-0192

WORK AROUND Sleep for a few milliseconds (just one often works) in the child process. -- ###@###.### 2002/11/26
11-10-0192