Your project relies on undefined behavior.
Any signal handler can safely make only calls to async-signal-safe functions. Any other function call invokes undefined behavior. Relying on the Java/Dalvik/ART virtual machine to limit itself to async-signal-safe function calls in any situation is unrealistic at best and quite likely just plain incorrect.
Your handler for an arbitrary signal can be called at any time, leaving the VM in any possible state. There is no way to safely make Java calls from a JNI signal handler, and it's unreasonable to expect anyone to even try supporting such calls - how could a VM's designers allow a signal to interrupt any synchronized
method if the signal handler were allowed to make calls synchronized
on the same object? If they did that, they'd break the language by violating the very meaning of synchronized
. But if they didn't do that, they'd allow deadlocks as such calls would try to lock an object that can never be unlocked because the signal interrupted processing.
In short, Java calls via JNI from a signal handler are fundamentally unsupportable.
The fact that they used to work for you only gave you an expectation that they would continue to do so.
You were lucky in the past.
It no longer works, and you can't expect it to work in the future.
And even if you hack it into working for you somehow, it's still fundamentally unsound. The only calls that are safe to make from within a signal handler, per the POSIX standard, are:
The following table defines a set of functions that shall be either
reentrant or non-interruptible by signals and shall be
async-signal-safe. Therefore applications may invoke them, without
restriction, from signal-catching 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 in the above table are considered to be unsafe with respect to signals. In the presence of signals, all functions defined by this volume of IEEE Std 1003.1-2001 shall behave as defined when called from or interrupted by a signal-catching function, with a single exception: when a signal interrupts an unsafe function and the signal-catching function calls an unsafe function, the behavior is undefined.
Since there is no way you can ever guarantee that making a Java call via JNI from within a signal handler will only make calls to async-signal-safe functions, there's no way you can ever expect anything but undefined behavior.