2012-10-29 8 views
5

Gibt es eine Möglichkeit, bestimmte Signale zu blockieren und andere Signale im selben Satz freizugeben? Ich schein einfach nicht meinen Kopf drum herum zu bekommen!posix threads block signal und entsperren

Ein Beispiel

sigset_t set; 
sigemptyset(&set); 

sigaddset(&set, SIGUSR1); 
// Block signal SIGUSR1 in this thread 
pthread_sigmask(SIG_BLOCK, &set, NULL); 
sigaddset(&set, SIGALRM); 
// Listen to signal SIGUSR2 
pthread_sigmask(SIG_UNBLOCK, &set, NULL); 


pthread_t printer_thread1, printer_thread2; 
pthread_create(&printer_thread1, NULL, print, (void *)&f1); 
pthread_create(&printer_thread2, NULL, print, (void *)&f2); 

bool tl = true; 
while(1) 
{ 
    if(tl) 
    { 
     // thread1 does something 
     kill(pid, SIGUSR1); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
    else 
    { 
     // thread2 does something 
     kill(pid, SIGUSR2); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
} 

ich nicht erlaubt ist Mutexs, Semaphore etc nur Signale zu verwenden.

Kann jemand helfen? :)

+0

Blockieren und entblockieren Sie SIGUSR1 nicht zuerst? Zur Zeit des UNBLOCK enthält die Menge sowohl SIGUSR1 als auch SIGALRM. – amaurea

Antwort

9

Gibt es eine Möglichkeit, bestimmte Signale zu blockieren und andere Signale in das gleiche Set zu entsperren?

Mit pthread_sigmask, können Sie entweder:

  • einen Satz von Signalen auf den Satz von blockierten Signale hinzufügen, mit der konstanten SIG_BLOCK
  • entfernen, um einen Satz von Signalen auf den Satz von blockiert Signale, die konstanten SIG_UNBLOCK
  • definiert den Satz von Signalen unter Verwendung blockiert werden, die konstante SIG_SET
Verwendung

Mit anderen Worten, es gibt einen aktuellen Satz blockierter Signale für den Thread, und Sie können ihn wie oben beschrieben einzeln ändern.

Der wichtige Punkt ist, dass neu erstellte Threads die Signalmaske des erzeugenden Threads erben, so dass Sie die Maske des neuen Threads direkt vor dem Erstellen oder in der Funktion, die der neue Thread ausführen wird, nach Belieben festlegen können .

In Bezug auf Ihr Beispiel, nehme ich an, dass Sie printer_thread1 Block SIGUSR2 und SIGALRM, haben versuchen und haben printer_thread2 Block SIGUSR1 und SIGALRM und haben den Haupt-Thread Block SIGUSR1 und SIGUSR2, so dass jeder Thread ein Signal senden kann, das wird von einem einzigen Thread abgefangen werden (ohne den Code print, f1 und f2, ist es unmöglich zu wissen, was Ihre Absicht in Ihrem Beispiel ist).

soll es möglich sein, dass durch den folgenden Code zu erreichen:

sigset_t set; 
pthread_t printer_thread1, printer_thread2; 


// Block signal SIGUSR1 & SIGALRM in printer_thread1 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_SET, &set, NULL); 
pthread_create(&printer_thread1, NULL, print, (void *)&f1); 

// Block signal SIGUSR2 & SIGALRM in printer_thread2 
sigaddset(&set, SIGUSR2); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_SET, &set, NULL); 
pthread_create(&printer_thread2, NULL, print, (void *)&f2); 

// Block signal SIGUSR1 & SIGUSR2 in the main thread 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
sigaddset(&set, SIGUSR2); 
// Listen to signal SIGALRM 
pthread_sigmask(SIG_SET, &set, NULL); 


bool tl = true; 
while(1) 
{ 
    if(tl) 
    { 
     // thread1 does something 
     kill(pid, SIGUSR1); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
    else 
    { 
     // thread2 does something 
     kill(pid, SIGUSR2); 
     // main thread waits for SIGALRM 
     sigwait(&set, &sig); 
     tl = !tl; 
    } 
} 

sehen diesen Manpages:

für weitere Details.

+0

Danke, das macht Sinn, aber es funktioniert eigentlich nicht mit den Drucker-Threads. Aber ich verstehe, wie die Masken jetzt funktionieren. – Max

1

Ich denke, was Sie hier tun möchten, ist

// Block signal SIGUSR1 in this thread 
sigemptyset(&set); 
sigaddset(&set, SIGUSR1); 
pthread_sigmask(SIG_BLOCK, &set, NULL); 

// Listen to signal SIGALRM 
sigemptyset(&set); 
sigaddset(&set, SIGALRM); 
pthread_sigmask(SIG_UNBLOCK, &set, NULL); 

Das Set nur sie verwendet wird, zu sagen, was zu sperren oder zu entsperren. Sobald der Befehl an den Befehl übergeben wurde, können Sie ihn zurücksetzen und eine weitere Signalmaske erstellen. Wenn Sie das sigemptyset überspringen, enthält das Set weiterhin SIGUSR1, das anschließend wieder entsperrt wird. Nun, ich denke, so funktioniert es zumindest - es ist lange her, seit ich Signale benutzt habe.