Wenn Sie eine Java-Anwendung in Kombination mit OSS verwenden, das in einer anderen Sprache erstellt wurde, wird möglicherweise eine hs_err_pid-Datei erstellt, die einen unbeabsichtigten Vorgang wie eine abnormale Beendigung verursacht. Meistens ist es ein sehr einfacher Fehler, aber ich werde ihn notieren, da er durch einen Konflikt zwischen JavaVM- und OSS-Signalhandlern verursacht werden kann.
Wenn JavaVM SIGSEGV, SIGBUS, SIGFPE, SIGPIPE und SIGILL signalisiert, scheint es die laufende Anweisung zu beurteilen und sie NullPointerException zuzuordnen. Wenn Sie diese Signalhandler jedoch mit OSS oder Ihrer eigenen Bibliothek überschreiben, wird das ursprünglich von Java generierte Signal von OSS ohne Erlaubnis interpretiert, was zu einem unbeabsichtigten Betrieb führt.
Abgesehen von meiner eigenen Bibliothek ist es schwierig, Kernteile wie die OSS-Signalsteuerung zu ändern. Als Java-Funktion wird ein Mechanismus (Signalkette) bereitgestellt, der den Signalhandler nicht umschreibt.
Registrierung der Signalkettenbibliothek
export LD_PRELOAD=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el7_6.x86_64/jre/lib/amd64/libjsig.so
Starten Sie einfach die Java-Anwendung nach diesem Setup.
Signalhandler werden bei Systemaufrufen wie Signal und Sigaction registriert. Durch Setzen der Umgebungsvariablen LD_PRELOAD auf libjsig.so wird sichergestellt, dass diese Systemaufrufe über die in libjsig.so implementierte Funktion mit demselben Namen registriert werden und den von JavaVM registrierten Signalhandler nicht überschreiben. Wenn ein Signal erzeugt wird, arbeitet der JavaVM-Signalhandler daher bevorzugt, und wenn das Signal nicht in Java erzeugt wird, wird die Verarbeitung an den in OSS oder dergleichen registrierten Signalhandler verkettet.
Eine Sequenz zum Registrieren von R-Sprachsignal-Handlern von rJava.
Rengine() # rJava: jri/Rengine.java
-> Java_org_rosuda_JRI_Rengine_rniSetupR() # rJava: jri/src/Rengine.c
-> initR() # rJava: jri/src/Rinit.c
-> setup_Rmainloop() # R: src/main/main.c
-> init_signal_handlers() # R: src/main/main.c(Abschnitt zur Registrierung des Signalhandlers)
c:src/main/main.c(R-3.6.0)
static void init_signal_handlers(void)
{
/* <FIXME> may need to reinstall this if we do recover. */
struct sigaction sa;
signal_stack = malloc(SIGSTKSZ + R_USAGE);
if (signal_stack != NULL) {
sigstk.ss_sp = signal_stack;
sigstk.ss_size = SIGSTKSZ + R_USAGE;
sigstk.ss_flags = 0;
if(sigaltstack(&sigstk, NULL) < 0)
warning("failed to set alternate signal stack");
} else
warning("failed to allocate alternate signal stack");
sa.sa_sigaction = sigactionSegv;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_ONSTACK | SA_SIGINFO;
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, &sa, NULL);
#endif
signal(SIGINT, handleInterrupt);
signal(SIGUSR1, onsigusr1);
signal(SIGUSR2, onsigusr2);
signal(SIGPIPE, handlePipe);
}
Dadurch wird der zur Steuerung von JavaVM erforderliche Signalhandler überschrieben, wodurch JavaVM nicht ordnungsgemäß funktioniert.
Seien Sie vorsichtig, wenn andere Signalhandler als libjvm.so im Abschnitt "Signalhandler" von hs_err_pid
Signal Handlers:
SIGSEGV: [libjvm.so+0xade3c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGBUS: [libjvm.so+0xade3c0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGFPE: [libNative.so+0x7d5], sa_mask[0]=00000000000000000000000000000000, sa_flags=SA_RESTART|SA_SIGINFO
SIGPIPE: [libNative.so+0x7d5], sa_mask[0]=00000000000000000000000000000000, sa_flags=SA_RESTART|SA_SIGINFO
SIGXFSZ: [libjvm.so+0x8ce930], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGILL: [libNative.so+0x7d5], sa_mask[0]=00000000000000000000000000000000, sa_flags=SA_RESTART|SA_SIGINFO
SIGUSR1: SIG_DFL, sa_mask[0]=00000000000000000000000000000000, sa_flags=none
SIGUSR2: [libjvm.so+0x8ce7e0], sa_mask[0]=00000000000000000000000000000000, sa_flags=SA_RESTART|SA_SIGINFO
SIGHUP: [libjvm.so+0x8ce9f0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGINT: [libjvm.so+0x8ce9f0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGTERM: [libjvm.so+0x8ce9f0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
SIGQUIT: [libjvm.so+0x8ce9f0], sa_mask[0]=11111111011111111101111111111110, sa_flags=SA_RESTART|SA_SIGINFO
Java Platform, Standard Edition - Handbuch zur Fehlerbehebung> 7 Umgang mit Signalen und Ausnahmen
Ein einfaches Beispiel für JNI (ein Programm, das Hello World anzeigt)
Recommended Posts