Gemeinsame Daten in einem Signal-Handler lesen

8

Ich bin in einer Situation, in der ich einen binären Suchbaum (BST) in einem Signal-Handler lesen muss ( SIGSEGV Signal-Handler, der nach meinem Wissen pro Thread-Basis ist). Die BST kann von den anderen Threads in der Anwendung geändert werden.

Nun, da ein Signal-Handler keine Semaphore, Mutexe usw. verwenden kann und daher nicht auf geteilte Daten zugreifen kann, Wie löse ich dieses Problem? Beachten Sie, dass meine Anwendung Multithread ist und auf einem Multicore-System ausgeführt wird.

    
MetallicPriest 13.12.2011, 16:00
quelle

4 Antworten

4

Sie sollten nicht auf freigegebene Daten vom Signal-Handler zugreifen. Sie können mehr Informationen über Signale in folgenden Artikeln finden:

Linux-Signale für den Anwendungsprogrammierer

Das Linux-Signal-Handling-Modell

Alles über Linux-Signale

Sieht so aus, als ob der sicherste Weg, mit Signalen in Linux umzugehen, signalfd ist.

    
ILYA Khlopotov 13.12.2011 16:15
quelle
3

Angenommen, der SH kann nicht direkt auf die geteilten Daten zugreifen, dann könnten Sie es vielleicht indirekt tun:

  1. Haben Sie eine globale Variable, die nur Signalhandler schreiben können, die aber von woanders gelesen werden kann (auch wenn nur innerhalb desselben Threads).
  2. SH setzt das Flag, wenn es aufgerufen wird
  3. Threads fragen dieses Flag ab, wenn sie nicht gerade dabei sind, die BST zu modifizieren; Wenn sie gefunden werden, führen sie die Verarbeitung durch, die für das ursprüngliche Signal erforderlich ist (unter Verwendung der erforderlichen Synchronisationen) und dann ein unterschiedliches Signal (wie SIGUSR1) aufbringen, um anzuzeigen, dass die Verarbeitung abgeschlossen ist
  4. Das Signal SH für THAT setzt das Flag
  5. zurück

Wenn Sie sich Sorgen über überlappende SIGSEGVs machen, fügen Sie dem Mix einen Zähler hinzu, um den Überblick zu behalten. (Hey! Du hast gerade deinen eigenen Semaphor gebaut!)

Die schwache Verbindung hier ist offensichtlich die Abstimmung, aber es ist ein Anfang.

    
Scott Hunter 13.12.2011 16:18
quelle
3

Ich kann zwei ziemlich saubere Lösungen sehen:

  1. Linux-spezifisch: Erstellen Sie dedizierte Thread-Handling-Signale. Fangen Sie Signale mit signalfd () . Auf diese Weise behandeln Sie Signale in einem normalen Thread und nicht in einem eingeschränkten Handler.
  2. Portable: Verwenden Sie auch einen dedizierten Thread, der schläft, bis das Signal empfangen wird. Sie können eine Pipe verwenden, um ein Paar Dateideskriptoren zu erstellen. Der Thread kann (2) vom ersten Deskriptor lesen und in einem Signal-Handler können Sie (2) in den zweiten Deskriptor schreiben. Die Verwendung von write () in einem Signal-Handler ist gemäß POSIX . Wenn der Thread etwas aus der Pipe liest, muss er eine Aktion ausführen.
Daper 02.12.2012 16:58
quelle
1

Sie könnten mmap in Erwägung ziehen, wenn Sie fuse Dateisystem (im Benutzerbereich).

Tatsächlich wirst du auf Gnu Hurd , die Unterstützung für externe Pager

Und vielleicht könnte Ihr Hack beim Lesen eines binären Suchbaums in Ihrem Signal-Handler oft in der Praxis funktionieren, nicht portabel und in einer Kernel-Versions-abhängigen Weise. Vielleicht Serialisierung des Zugriffs mit Low-Level nicht tragbaren Tricks (zB futexes und atomare gcc-Builtins ) könnte funktionieren. Das Lesen des (maschinenspezifischen) Quellcodes von NPTL, d. H. Aktuellen Linux-pthread-Routinen, sollte helfen.

Es könnte wahrscheinlich der Fall sein, dass pthread_mutex_lock etc tatsächlich innerhalb eines Linux-Signal-Handlers verwendet werden kann (weil es wahrscheinlich nur futex und atomare Anweisungen gibt).

    
Basile Starynkevitch 13.12.2011 17:53
quelle