JDK-4954748 : Problem with JNI when using NPTL (invoking system() 10x per thread in parallel)
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2003-11-14
  • Updated: 2012-11-02
  • Resolved: 2003-11-17
Related Reports
Duplicate :  
Relates :  
Relates :  
Description

Name: jl125535			Date: 11/14/2003


FULL PRODUCT VERSION :
java version "1.4.2_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_02-b03)
Java HotSpot(TM) Client VM (build 1.4.2_02-b03, mixed mode)


FULL OS VERSION :
Linux rhel.versedge.com 2.4.21-4.EL #1 Fri Oct 3 18:13:58 EDT 2003 i686 i686 i386 GNU/Linux
This is RHEL 3.0

EXTRA RELEVANT SYSTEM CONFIGURATION :
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-20)


A DESCRIPTION OF THE PROBLEM :
When using JNI calls in multi-threaded program, the native call ("system()") sometimes return with error of "No child processes".

When setting LD_ASSUME_KERNEL=2.4, the problem disapear.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Below is a small program to reproduce it. In general, the program creates two threads which invoking "system" system call 10 times each in parallel.

Create the two files below and run the following commands:
> /usr/java/j2sdk1.4.2_02/bin/javac LinuxBug.java
> cc -I /usr/java/j2sdk1.4.2_02/include -I /usr/java/j2sdk1.4.2_02/include/linux LinuxBug.c -shared -o libLinuxBug.so
> /usr/java/j2sdk1.4.2_02/bin/java -Djava.library.path=`pwd` LinuxBug





ERROR MESSAGES/STACK TRACES THAT OCCUR :
"No child processes" (from strerror)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
LinuxBug.java
-------------
public class LinuxBug extends Thread {
        public LinuxBug (String cmd) {
                m_cmd = cmd;
        }

        public void run () {
                for (int j=0; j<10; j++) {
                    int i = systemCall (m_cmd);
                    System.out.println ("systemCall " + m_cmd + " ("
                                        +j+") return " + i);
                }
        }

        private String m_cmd = null;

    native static int systemCall (String arg);
    public static void main (String argv[])
   {
        System.loadLibrary("LinuxBug");
        LinuxBug lb1 = new LinuxBug ("echo thread 1 ");
        LinuxBug lb2 = new LinuxBug ("echo thread 2 ");
        lb1.start();
        lb2.start();
   }
}

LinuxBug.c
----------
#include <jni.h>
#include <errno.h>

#ifndef _Included_LinuxBug
#define _Included_LinuxBug^M
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     LinuxBug
 * Method:    systemCall
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_LinuxBug_systemCall
  (JNIEnv *env, jclass class , jstring cmd)
{
        const char *source = (*env)->GetStringUTFChars(env, cmd, 0);
        int res = 0;
        res = system(source);
        if(res != 0) {
                int rest=errno;
                printf ("system return code=%d (%s)\n", res, strerror(rest));
                res = rest;
        }
        (*env)->ReleaseStringUTFChars(env, cmd, source);
        return res;
}
#ifdef __cplusplus
}
#endif
#endif

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

CUSTOMER SUBMITTED WORKAROUND :
export LD_ASSUME_KERNEL=2.4
(Incident Review ID: 218170) 
======================================================================

Comments
EVALUATION See also 4763362. The fix in 1.4.2 only fixed Java Runtime.exec() calls. The same waitpid problem still exists if a Java app never calls Runtime.exec() and a child process is forked in JNI code (see also 4945203). The 1.5 fix is 4785154. ###@###.### 2003-11-17
17-11-2003

WORK AROUND Due to the fix of 4763362, calling Runtime.getRuntime().exec() in 1.4.2 will cause JDK to override default JVM SIGCHLD handler, so a possible workaround is to call exec() first in Java code, before any fork() or system() call in JNI code. For example, adding this to the beginning of main() can get around the problem: try { Runtime.getRuntime().exec(System.getProperty("user.dir")); } catch (Exception x) {} Executing current directory is harmless, it should always fail, but as a side effect in 1.4.2 JDK, it will disable JVM SIGCHLD handler. ###@###.### 2003-11-17
17-11-2003