Hinweise zur Signalsteuerung in Java

Hinweise zur Signalsteuerung in Java

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.

Beziehung zwischen Java und Signalen

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.

Problemumgehung

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.

Kommentar

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.

Fallstudie

Bei Verwendung der R-Sprache aus Java mit rJava

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.

Keine Signalkette

  1. JavaVM registriert einen Signalhandler
  2. Laden Sie die R-Sprache aus rJava
  3. Die R-Sprache registriert den Signalhandler

Es gibt eine Signalkette

  1. Registrieren Sie die Signalkettenbibliothek bei LD_PRELOAD
  2. JavaVM registriert einen Signalhandler
  1. Laden Sie die R-Sprache aus rJava
  2. Die R-Sprache registriert den Signalhandler

Protokolldatei hs_err_pid

Seien Sie vorsichtig, wenn andere Signalhandler als libjvm.so im Abschnitt "Signalhandler" von hs_err_pid .log registriert sind, der beim Absturz einer Java-Anwendung erstellt wird. (Im folgenden Beispiel ist libNative.so ein benutzerdefinierter Signalhandler.)

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

Referenz

Recommended Posts

Hinweise zur Signalsteuerung in Java
Laden Sie Notizen in Java auf S3 hoch und laden Sie sie herunter
Java-Versionsverwaltung unter macOS
Hinweise zur Verwendung regulärer Ausdrücke in Java
Java Note
Hinweise zum Java-Pfad und -Paket
Hinweise zu Operatoren, die Java ~ String type ~ verwenden
Versionsverwaltung von Java mit jenv von OSX
Hinweise zu JSP-Erweiterungs-Tags in SpringFrameWork
Java-Steuerungssyntax
Java-Steuerungssyntax
Partisierung in Java
Java Generics (Hinweise)
Änderungen in Java 11
[Java] Array-Hinweis
Janken in Java
[Java] Studiennotizen
Hinweise zur Java-Serialisierung
Umfangsrate in Java
FizzBuzz in Java
Organisiertes Memo im Kopf (Java - Control Syntax)
Deserialisieren Sie CSV in Java basierend auf dem Headernamen
Hinweise zum Schreiben von Kommentaren auf Englisch
Hinweise zur Implementierung der Google Books-API in den Versionen Java Okhttp und Gson sowie Okhttp und Jackson
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Hinweise zu Protokollpuffern
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
[Java] Stream Collectors Hinweis
Java-formatierte Ausgabe [Hinweis]
Verbinden Sie Arrays in Java
"Hallo Welt" in Java
Aufrufbare Schnittstelle in Java
Installieren Sie Java auf dem Mac
Kommentare in der Java-Quelle
[Android] Hinweise zu XML
Azure funktioniert in Java
Führen Sie PostgreSQL unter Java aus
Formatieren Sie XML in Java
Hinweise zur Mehrfachvererbung
Überprüfungshinweise zu Java NIO 2
Einfache HTML-Spezialchars in Java
Hinweise zu regulären Ausdrücken
Boyer-Moore-Implementierung in Java
Hallo Welt in Java
Verwenden Sie OpenCV mit Java
WebApi-Memorandum mit Java
Typbestimmung in Java
Befehle in Java ausführen (Ping)
Verschiedene Threads in Java
Implementierung der Heap-Sortierung (in Java)
Zabbix API in Java
ASCII-Kunst in Java
Listen in Java vergleichen