Abgesehen von dem Problem "zu viele Signale" können Signale explizit ignoriert werden. Von man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Signale können auch blockiert werden. Von man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Sowohl blockierte als auch ignorierte Signalmengen werden von untergeordneten Prozessen geerbt. Daher kann es vorkommen, dass der übergeordnete Prozess Ihrer Anwendung eines dieser Signale ignoriert oder blockiert hat.
Was passiert, wenn mehrere Signale geliefert werden, bevor der Prozess die Verarbeitung der vorherigen beendet hat? Das hängt vom Betriebssystem ab. Die signal(2)
oben verlinkte Manpage beschreibt dies:
- System V würde die Signaldisposition auf die Standardeinstellung zurücksetzen. Schlimmer noch, eine schnelle Übermittlung mehrerer Signale würde zu rekursiven (?) Aufrufen führen.
- BSD würde das Signal automatisch blockieren, bis der Handler fertig ist.
- Unter Linux hängt dies von den für GNU gesetzten Kompilierungsflags ab
libc
, aber ich würde das BSD-Verhalten erwarten.
signal(2)
darauf hingewiesen, dass Sie diese Verwirrung vermeiden, indem Siesigaction(2)
stattdessen verwenden.Sie können nicht darauf vertrauen, dass jedes gesendete Signal zugestellt wird. Beispielsweise "verschmilzt" der Linux-Kernel SIGCHLD, wenn ein Prozess bei der Verarbeitung von SIGCHLD aus einem verlassenen untergeordneten Prozess lange dauert.
Um einen anderen Teil Ihrer Frage zu beantworten, werden Signale im Kernel "in die Warteschlange gestellt", wenn mehrere verschiedene Signale in einem zu kurzen Intervall eintreffen.
Sie sollten verwenden
sigaction()
, um den Signalhandler mit demsa_sigaction
Mitglied von einzurichten undsiginfo_t
dassa_mask
Mitglied dessiginfo_t
Arguments sorgfältig festzulegen. Ich denke, dies bedeutet, zumindest alle "asynchronen" Signale zu maskieren. Laut der Manpage für Linuxsigaction()
maskieren Sie auch das Signal, das verarbeitet wird. Ich denke, Sie sollten dassa_flags
Mitglied auf SA_SIGINFO setzen, aber ich kann mich nicht erinnern, warum ich diesen Aberglauben habe. Ich glaube, dies wird Ihrem Prozess einen Signalhandler geben, der ohne Rennbedingungen eingestellt bleibt und der nicht von den meisten anderen Signalen unterbrochen wird.Schreiben Sie Ihre Signalhandlerfunktion sehr, sehr sorgfältig. Stellen Sie einfach eine globale Variable ein, um anzuzeigen, dass ein Signal abgefangen wurde, und lassen Sie den Rest des Prozesses die gewünschte Aktion für dieses Signal ausführen. Auf diese Weise werden die Signale für die geringste Zeit maskiert.
Außerdem sollten Sie Ihren Signalverarbeitungscode sehr gründlich testen. Stellen Sie es in einen kleinen Testprozess und senden Sie so viele SIGUSR1- und SIGUSR2-Signale wie möglich, möglicherweise von 2 oder 3 speziellen Signal-Sendeprogrammen. Mischen Sie auch einige andere Signale ein, nachdem Sie sicher sind, dass Ihr Code SIGUSR1 und SIGUSR2 schnell und korrekt verarbeiten kann. Bereiten Sie sich auf schwieriges Debuggen vor.
Wenn Sie Linux und nur Linux verwenden, können Sie
signalfd()
einen Dateideskriptor erstellen, den Sie abrufenselect()
oder abfragen können, um diese Signale zu empfangen. Die Verwendungsignalfd()
erleichtert möglicherweise das Debuggen.quelle
Es wird garantiert, dass ein Signal in dem Sinne geliefert wird, dass ein Prozess erfolgreich aufgerufen wird
kill
dann empfängt das Ziel das Signal. Dies ist asynchron: Der Absender kann nicht wissen, wann das Signal empfangen oder verarbeitet wird. Dies garantiert jedoch nicht, dass das Signal geliefert wird. Das Ziel könnte sterben, bevor es das Signal verarbeiten kann. Wenn das Ziel das Signal zum Zeitpunkt der Übermittlung ignoriert, hat das Signal keine Auswirkung. Wenn das Ziel mehrere Instanzen derselben Signalnummer empfängt, bevor es sie verarbeiten kann, können (und werden) die Signale zusammengeführt: Wenn Sie dasselbe Signal zweimal an einen Prozess senden, können Sie nicht wissen, ob der Prozess das Signal empfängt ein-oder zweimal. Signale dienen hauptsächlich dazu, einen Prozess abzubrechen oder einen Prozess aufmerksam zu machen. Sie sind nicht für die Kommunikation als solche konzipiert.Wenn Sie eine zuverlässige Lieferung benötigen, benötigen Sie einen anderen Kommunikationsmechanismus. Es gibt zwei Hauptkommunikationsmechanismen zwischen Prozessen: Eine Pipe ermöglicht eine unidirektionale Kommunikation; Ein Socket ermöglicht die bidirektionale Kommunikation und mehrere Verbindungen zum selben Server. Wenn das Ziel so viele Benachrichtigungen verarbeiten soll, wie Sie es senden, senden Sie Bytes über eine Pipe.
quelle
Der Kernel kann Standardsignale zusammenführen, wenn mehr als eines im blockierten Zustand geliefert wird. Echtzeitsignale sind dagegen nicht ähnlich behindert.
Aus der Handbuchseite von Signal (7) :
Versuchen Sie es mit einem Signal mit einer Nummer im Bereich von SIGRTMIN bis SIGRTMAX.
quelle
ulimit -i
zeigt diesen Wert als 63432 unter Ubuntu 18.04.