Homepage    Computer-Stoff(Titelseite)   Threads(Titelseite)

Signale und Threads

Die Verwendung von Signalen im Zusammenhang mit Threads ist nicht unproblematisch. Wenn es anders geht, sollte man darauf verzichten. Leider ist dies nicht immer möglich.


Normale Signale und Multi-Thread-Programme

Programme, in denen mehrere Threads laufen, können Signale versenden und empfangen genau wie alle anderen Programm auch. Falls mehrere Threads das Signal empfangen können, hängt es von der Implementation ab, welcher Thread das Signal nun tatsächlich empfängt. Der POSIX-Standart legt fest, daß eigentlich jeder Thread das Signal empfangen sollte.

Manchmal spielt dies auch keine so große Rolle. Schickt man beispielsweise ein SIGKILL, ist es egal, welcher Thread das Signal empfängt: Er beendet den Prozeß und alle Threads lösen sich in Nichts auf.

In der pthread-Implementation für Linux hat jeder thread seine eigene Prozeß-ID. Deshalb kann man Signale schon mit dem normalen kill-Befehl an einen bestimmten Thread zu schicken. Streng genommen ist das ein Fehler inder Linux-Implementierung von Threads, aber oft ist es sehr praktisch.

Man beachte aber, daß, wenn man in einem Thread einen SignalHandler setzt, dieser sofort auch für allen anderen Threads gültig ist. Insbesondere macht es in Programmen mit mehreren Threads im Allgemeinen keinen Sinn, SignalHandler hin und her zu setzen.


Signale an einen bestimmten Thread schicken

Hierzu gibt es den Befehl

int pthread_kill (pthread_t th, int sig);

th ist der Thread, an den das Signal geschickt werden soll, sig ist das Signal. Einen SignalHandler kann man ganz normal mit der Funktion signal gesetzt werden. Diese Einstellung ist dann allerdings für alle Threads gültig. Immerhin hat man die Möglichkeit, thread-spezifische Signal-Masken zu setzen.


thread-spezifische Signal-Masken

Genau wie bei einem normalen Prozeß kann man einem Thread mittels einer Signalmaske mitteilen, welche Signale er ignorieren soll oder welche er blockieren soll. Ganz analog zu den Befehlen sigsetmask und siggetmask gibt es hier den Befehl

int pthread_sigmask (int how, 
                     const sigset_t *newmask,
                     sigset_t *oldmask);

wobei how die Werte SIG_SETMASK, SIG_BLOCK und SIG_UNBLOCK haben kann. Für die Argumente vom Typ sigset_t siehe die man-pages der Funktionen sigaddset, sigemptyset usw..


SIGUSR1 und SIGUSR2

In alten Kerneln (<=2.1) werden die beiden Signale SIGUSR1 und SIGUSR2 von den Linux-Threads selber dazu benutzt, Threads anzuhalten oder weiterlaufen zu lassen, wenn sie durch einen Mutex blockiert waren, oder auch für einige weitere Operationen. Man kann diese beiden also nicht mehr selber benutzen. Ab Kernel 2.2. und mit der glibc kann man sie benutzen.


Fallen mit Threads und Signalen

Mutexe und Signalhandler: wandert ein Thread in einen Signalhandler, während er einen Mutex gesetzt hat, so bleibt der Mutex gesetzt. Beendet sich der Thread insbesondere im Signalhandler, so bleiben in diesem Fall alle anderen Threads, die diesen Mutex brauchen, hängen, und zwar für immer, denn es kann nun niemand mehr den Mutex freigeben.


Homepage   Computer-Stoff(Titelseite)   Threads(Titelseite) by Michael Becker, 6/2001 Letzte Änderung: 12/2002.