JDK-4945203 : JAVA BEHAVIOR FOR REAPING THE STATUS OF FORKED PROCESS
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.3.1_09
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2003-10-29
  • Updated: 2012-11-02
  • Resolved: 2003-10-29
Related Reports
Duplicate :  
Relates :  
Description

Name: wm7046			Date: 10/28/2003


We are seeing difference in the way java behaves in linux and other platforms
for the sample code given below. We need to know if this is linux specific
java issue and provide a solution / workaround for the same.

  Description of the sample code :
----------------------------------------
JAVA loads a "C" Shared library using System.loadLibrary.
The "C" library has a routine to fork a process and the parent will
do a waitpid with WNOHANG option to get the status of the forked process
in a loop.
Once the forked process exits, the parent which is in a loop is supposed
to get the status of its child, On all platforms we see that the parent
process gets the status of its child but in case of Linux we see that
the thread other than parent  reaps the status.

Sample Code  and steps to reproduce :
------------ -------------------------------------
(1)
HelloWorld.java
class HelloWorld {
               public native void displayHelloWorld();

               static {
                   System.loadLibrary("hello");
              }

              public static void main(String[] args) {
                  new HelloWorld().displayHelloWorld();
              }
          }

(2)Make Class File
javac HelloWorld.java

(3)Make .h file
javah -jni HelloWorld

(4)Write a "C" program for generating a "C" shared library which will be
   loaded by java
HelloWorldImp.c
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

#include <jni.h>
#include "HelloWorld.h"
#include <stdio.h>

JNIEXPORT void JNICALL
Java_HelloWorld_displayHelloWorld(JNIEnv *env, jobject obj)
{
   int ret, status, pid, main_pid;
   pid=fork();
   if(pid == 0)
   {
      sleep(10);
      printf("\n\n Child Exiting now");
      exit(0);
   }
   else
   {
      while(1)
      {
         printf("Waiting for child process id %d \n", pid);

         printf("I am parent my pid is %d and my child pid is %d \n",
getpid(), pid);
         main_pid = waitpid(pid, &status, WNOHANG);
         printf("Retval from waitpid is %d \n", main_pid);

         if(main_pid > 0)
            break;
         if((main_pid < 0 ) && (errno != EINTR))
            break;
         sleep(1);
      }
      if (main_pid == -1)
         printf("Retval from waitpid after while loop is %d errno is %d \n", main_pid, errno);
      printf("status is %d, exitstatus is %d" , status, WEXITSTATUS(status));
   }
}

(5)Generate "C" shared library
set JAVAHOME to 131
gcc -g -c HelloWorldImp.c -I $JAVAHOME/include -I $JAVAHOME/include/linux
gcc -o libhello.so -shared HelloWorldImp.o

Run the sample program
java HelloWorld

After this we will see that our parent in libhello.so will never get
the status of its child and it will come out of the loop once the child
terminates,  with ECHILD, this is because other thread in java would have reaped the status.


We see that the status of the child is delivered to the correct java thread in case of other
platforms but in linux we dont see this behavior.
(Review ID: 218073) 
======================================================================

Comments
EVALUATION The problem is that Linux JDK installs SIGCHLD handler. The child process is reaped inside the SIGCHLD handler if it's not waited for (e.g. in this test case, parent is in sleep). It has been fixed in 1.5 under 4785154. To get around the problem, you could install an empty SIGCHLD handler to override the default JDK/JVM handler. But notice that Runtime.exec() before JDK1.4.1 depends on the SIGCHLD handler, if you override the default handler, you could run into problems if you use Runtime.exec(). JDK-1.4.1 and later do not rely on SIGCHLD handler. ###@###.### 2003-10-29
29-10-2003