ART prevents any Java calls from JNI during native signal processing

My project uses a crash capture and send module to the Android system. When you handle your own failure, the native code will do something and then make java calls from the JNI. He works well at Dalvik. But it does not work in the Android version above 5.0 using ART. Because ART prevents any Java calls from the JNI during native signal processing. It says that the ART signal processing uses an alternating signal stack, so can you call java methods during the signal transfer process? Are there any other ways?
Consumption:
1. Java call of the native method, but the failure of the native method.
2. Own emergency handler picks up a signal to handle the accident.
3. During the failure processing, the JNI method call, but failed

12-31 20:36:02.516 7845-7957 A/art: art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: JNI IsSameObject called with pending exception 'java.lang.StackOverflowError' thrown in... in call to IsSameObject stack=0x9fff8000-0x9fffa000 stackSize=1036KB 

Link: https://code.google.com/p/android/issues/detail?id=162663
It would be nice if someone who worked with ART and / or Bionic could learn this.

0
source share
1 answer

Your project depends on undefined behavior.

Any signal handler can safely make calls only for asynchronous signals. Any other function call causes undefined behavior. Relying on the Java / Dalvik / ART virtual machine to limit itself to being safe for asynchronous signals, function calls in any situation are unrealistic at best and most likely simply incorrect.

Your handler for an arbitrary signal can be called at any time, leaving the VM in any possible state. It is not possible to make Java calls safely from the JNI signal handler, and it is unreasonable to expect anyone to even try to support such calls - as virtual machine developers would allow the signal to interrupt any synchronized method if the signal handler were allowed to make synchronized calls on the same object? If they did, they would violate the language, violating the very meaning of synchronized . But if they did not, they will allow blocking, since such calls will try to block an object that can never be unlocked, because signal processing is interrupted.

In short, Java calls through JNI from a signal handler are fundamentally unacceptable.

The fact that they worked for you only gave you hope that they would continue to do so.

You're lucky in the past.

It no longer works, and you cannot expect it to work in the future.

And even if you somehow hack it into work, you are still fundamentally unfounded. The only calls that can be safely made from a signal handler are beyond the POSIX standard :

The following table defines a set of functions that should be either reentrant or not interrupted by signals and an asynchronous safety signal. Therefore, applications can refer to them without restriction, from signal capture functions:

 _Exit() _exit() abort() accept() access() aio_error() aio_return() aio_suspend() alarm() bind() cfgetispeed() cfgetospeed() cfsetispeed() cfsetospeed() chdir() chmod() chown() clock_gettime() close() connect() creat() dup() dup2() execle() execve() fchmod() fchown() fcntl() fdatasync() fork() fpathconf() fstat() fsync() ftruncate() getegid() geteuid() getgid() getgroups() getpeername() getpgrp() getpid() getppid() getsockname() getsockopt() getuid() kill() link() listen() lseek() lstat() mkdir() mkfifo() open() pathconf() pause() pipe() poll() posix_trace_event() pselect() raise() read() readlink() recv() recvfrom() recvmsg() rename() rmdir() select() sem_post() send() sendmsg() sendto() setgid() setpgid() setsid() setsockopt() setuid() shutdown() sigaction() sigaddset() sigdelset() sigemptyset() sigfillset() sigismember() sleep() signal() sigpause() sigpending() sigprocmask() sigqueue() sigset() sigsuspend() sockatmark() socket() socketpair() stat() symlink() sysconf() tcdrain() tcflow() tcflush() tcgetattr() tcgetpgrp() tcsendbreak() tcsetattr() tcsetpgrp() time() timer_getoverrun() timer_gettime() timer_settime() times() umask() uname() unlink() utime() wait() waitpid() write() 

All functions not listed in the table above are considered unsafe with respect to signals. If there are signals, all functions defined by this IEEE Std 1003.1-2001 volume must behave as defined when a signal capture function is called or interrupted, with one exception: when a signal interrupts an unsafe function and a signal- catching function calls an unsafe function, the behavior is undefined .

Since you can never guarantee that calling Java through the JNI from a signal handler will only make calls that are protected from asynchronous signals, you can never expect anything other than undefined behavior.

+2
source

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


All Articles