Signal processing in native code - with JVM failure with SIGSEGV in the terminal

This is my first post, so please show some understanding. I have java code and I have my own code.

Currently, the java part is not so interesting, so I will move on to the C ++ part:

//some more trivial includes #include <signal.h> //these are global variables jclass GLOBAL_CLASS; JNIEnv * GLOBAL_ENV; jobject GLOBAL_OBJECT; jmethodID METHOD_ID; void sigproc(int signo) { if (signo == SIGINT) { signal(SIGINT, sigproc); //if Ctrl-c is pressed I want to call a method within my java class //since I can pass only int to this function //I've decided to use global variables GLOBAL_ENV->CallVoidMethod(GLOBAL_OBJECT, METHOD_ID); exit(0); } } JNIEXPORT void JNICALL Java_intern_Work_readFromFile (JNIEnv *env, jobject obj, jobjectArray arr) { /*define a signal trap! */ signal(SIGINT, sigproc); //sigproc(SIGINT); /*initialize the global variables */ GLOBAL_ENV = env; GLOBAL_OBJECT = obj; GLOBAL_CLASS = env->GetObjectClass(obj); //method id is the same so it better to cache it //at the beginning jmethodID mid = env->GetMethodID(GLOBAL_CLASS, "nativeListener", "(Ljava/lang/String;)V"); METHOD_ID = GLOBAL_ENV->GetMethodID(GLOBAL_CLASS, "closeEverything", "()V"); //let say I have a while(true) block just below //and some more work is done. } 

This function runs at the beginning of my MainClass. The program works correctly if I delete

 GLOBAL_ENV->CallVoidMethod(GLOBAL_OBJECT, METHOD_ID); 

but the problem is that I need this because I plan to free some dynamic allocated memory + I need to call this function of my class. (in other words ... when I press ctrl-c in the terminal, it tells JVM cheshes with SIGSEGV)

It seems that I really do not understand what happens when a signal is transmitted from the core. Is my global variable GLOBAL_ENV the correct pointer that I can use?

Can someone tell me an elegant way to solve my problem? Or any guidance is appreciated! Any explanation ... at all. Thanks in advance!

Here is a sample JVM emergency code:

 A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x00007f9974cfc021, pid=7099, tid=140297087112960 # # JRE version: 6.0_24-b24 # Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops) # Derivative: IcedTea6 1.11.4 # Distribution: Ubuntu 12.04 LTS, package 6b24-1.11.4-1ubuntu0.12.04.1 # Problematic frame: # V [libjvm.so+0x617021] methodOopDesc::result_type() const+0x31 
+4
source share
2 answers

Your problem is that SIGINT is an asynchronous signal; this can happen between any two machine instructions if they are not locked.

This means that it is not safe to call anything other than asynchronous functions from your signal handler (and, if you want to be portable, you should not do anything other than set the sig_atomic_t variables). The JVM is certainly not considered asynchronous. Most likely, you interrupt the JVM in the middle of some important code, and your method call distorts the state of the JVM.

The approach commonly used to process SIGINT is to have a loop somewhere where the flag variable (such as sig_atomic_t ) is checked. When you get SIGINT , set the flag and return it. The loop will appear and execute the rest of the handler in a safe, synchronous manner.

In your case, you can simply create a Java thread that periodically calls the checkForInterrupt function, which checks the aforementioned flag variable. checkForInterrupt returns the current status of the flag, and then your thread can act on it.

Another option is to use a function like pause , sigwait or sigsuspend to pause the stream until a signal is received. Then the stream wakes up and processes the signal synchronously.

+6
source

Take a look at http://javajiggle.com/2008/01/06/if-jni-based-application-is-crashing-check-signal-handling/ It looks like this may be the problem you are describing.

Edit: this link is out of date, this is the information that was in it:

http://docs.oracle.com/javase/7/docs/technotes/guides/vm/signal-chaining.html

To use libjsig.so, either link it to the application that creates / implements the HotSpot VM, for example:

cc -L -ljsig -ljvm java_application.c

or use the LD_PRELOAD environment variable, for example:

export LD_PRELOAD = / libjsig.so; java_application (ksh)

setenv LD_PRELOAD / libjsig.so; java_application (csh)

The embedded signal () / sigset () / sigaction () returns the stored signal of the handlers, not the signal handlers installed by the Java HotSpot virtual machine, which are visible to the OS.

A signal chain object has been introduced to refer to Improvement Number 4381843.

+3
source

Source: https://habr.com/ru/post/1434319/


All Articles