FULL PRODUCT VERSION :
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Red Hat Enterprise Linux Server release 5.3 (Tikanga)
EXTRA RELEVANT SYSTEM CONFIGURATION :
This was tested on other RHEL Linux systems&machines, 32 or 64 bit, all failed.
It is supposed to work on Solaris machines (I did not test myself, I do not have any Solaris machine, but some collaborators told me they used to do it in their former job).
A DESCRIPTION OF THE PROBLEM :
The problem happens when using JNI and setting a new interrupt handler in C++ code to throw a C++ exception in place of the system interrupt.
The exception is not handled correctly by libjsig.so. Instead of having the exception propagated through C++ code (and allowing C++ to catch it), java exists complaining about an uncatched c++ exception.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1 - Create a InterruptTest.java file containing the code provided in the "Source code for an executable test case:" section of this bug. Its aim is just to call a native C++ function.
2 - Compile it with: javac MyInterrupt; javah -jni MyInterrupt
3- Create a native code file MyInterrupt.cpp containing the code provided in the "Source code for an executable test case:" section of this bug. This code sets the SIGSEGV signal handler and have it throw a C++ exception in case a system interrupt is raised. The JNI native call have an illegal access memory surrounded by try/catch blocs to catch the exception thrown by the interrupt handler.
4- Compile the native code with: g++ -m32 -fexceptions -fnon-call-exceptions -fPIC -shared -o libMyInterrupt.so MyInterrupt.cpp
5- run: LD_PRELOAD=libjsig.so java MyInterrupt
6- the java VM exits complaining about the C++ exception, I was expecting it to pass the exception onto the native code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Using the code test case below, the text that should be printed is:"
Trying a very bad access
Interrupted..
Exception catched!
Nice termination
"
This is what gets printed if I do not use libjsig.so but obviously not using jsig is not an alternative since in this case the interrupt caused by jvm errors would not be handled properly.
ACTUAL -
Using the code test case below, the actual output is:"
Trying a very bad access
Interrupted..
terminate called after throwing an instance of 'char const*'
zsh: abort LD_PRELOAD=libjsig.so java MyInterrupt
"
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
File MyInterrupt.java:
--->
class MyInterrupt {
private native void run();
public static void main(String[] args) {
new MyInterrupt().run();
}
static {
System.loadLibrary("MyInterrupt");
}
}
<--
File MyInterrupt.cpp
-->
#include <jni.h>
#include "MyInterrupt.h"
#include <stdio.h>
#include <signal.h>
// Initialization of the handlers at library loading time
struct Initialiser{
Initialiser(){
struct sigaction sa = {0};
sa.sa_handler = throwCppExcept;
if(sigaction(SIGSEGV,&sa, NULL) == -1){
printf("Error installing handler\n");
}
}
};
Initialiser i;// initialisation done when constructing this object
// native function called by Java/JNI
JNIEXPORT void JNICALL Java_MyInterrupt_run(JNIEnv *, jobject){
try{
int* p=NULL;
printf("Trying a very bad access\n");
*p = 1;
}catch(...){
printf("Exception catched!\n");
}
printf("Nice termination\n");
}
<--
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround known.
java version "1.6.0_12"
Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
Java HotSpot(TM) Server VM (build 11.2-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Red Hat Enterprise Linux Server release 5.3 (Tikanga)
EXTRA RELEVANT SYSTEM CONFIGURATION :
This was tested on other RHEL Linux systems&machines, 32 or 64 bit, all failed.
It is supposed to work on Solaris machines (I did not test myself, I do not have any Solaris machine, but some collaborators told me they used to do it in their former job).
A DESCRIPTION OF THE PROBLEM :
The problem happens when using JNI and setting a new interrupt handler in C++ code to throw a C++ exception in place of the system interrupt.
The exception is not handled correctly by libjsig.so. Instead of having the exception propagated through C++ code (and allowing C++ to catch it), java exists complaining about an uncatched c++ exception.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1 - Create a InterruptTest.java file containing the code provided in the "Source code for an executable test case:" section of this bug. Its aim is just to call a native C++ function.
2 - Compile it with: javac MyInterrupt; javah -jni MyInterrupt
3- Create a native code file MyInterrupt.cpp containing the code provided in the "Source code for an executable test case:" section of this bug. This code sets the SIGSEGV signal handler and have it throw a C++ exception in case a system interrupt is raised. The JNI native call have an illegal access memory surrounded by try/catch blocs to catch the exception thrown by the interrupt handler.
4- Compile the native code with: g++ -m32 -fexceptions -fnon-call-exceptions -fPIC -shared -o libMyInterrupt.so MyInterrupt.cpp
5- run: LD_PRELOAD=libjsig.so java MyInterrupt
6- the java VM exits complaining about the C++ exception, I was expecting it to pass the exception onto the native code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Using the code test case below, the text that should be printed is:"
Trying a very bad access
Interrupted..
Exception catched!
Nice termination
"
This is what gets printed if I do not use libjsig.so but obviously not using jsig is not an alternative since in this case the interrupt caused by jvm errors would not be handled properly.
ACTUAL -
Using the code test case below, the actual output is:"
Trying a very bad access
Interrupted..
terminate called after throwing an instance of 'char const*'
zsh: abort LD_PRELOAD=libjsig.so java MyInterrupt
"
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
File MyInterrupt.java:
--->
class MyInterrupt {
private native void run();
public static void main(String[] args) {
new MyInterrupt().run();
}
static {
System.loadLibrary("MyInterrupt");
}
}
<--
File MyInterrupt.cpp
-->
#include <jni.h>
#include "MyInterrupt.h"
#include <stdio.h>
#include <signal.h>
// Initialization of the handlers at library loading time
struct Initialiser{
Initialiser(){
struct sigaction sa = {0};
sa.sa_handler = throwCppExcept;
if(sigaction(SIGSEGV,&sa, NULL) == -1){
printf("Error installing handler\n");
}
}
};
Initialiser i;// initialisation done when constructing this object
// native function called by Java/JNI
JNIEXPORT void JNICALL Java_MyInterrupt_run(JNIEnv *, jobject){
try{
int* p=NULL;
printf("Trying a very bad access\n");
*p = 1;
}catch(...){
printf("Exception catched!\n");
}
printf("Nice termination\n");
}
<--
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
No workaround known.