Ohne eine Liste der aktuellen Threads zu behalten, versuche ich zu sehen, dass ein Echtzeit-Signal an alle Threads in meinem Prozess geliefert wird. Meine Idee ist, so vorzugehen:
pthread_sigmask
) für sich selbst und tritt wiederholt in eine Schleife ein, die raise(sig)
aufruft, bis sigpending
anzeigt, dass das Signal ansteht (es waren keine Threads mehr vorhanden, bei denen das Signal blockiert war). Das Problem, auf das ich stoße, ist, dass pthread_sigmask
nicht respektiert wird. Alles funktioniert gut, wenn ich das Testprogramm unter strace
starte (vermutlich aufgrund eines anderen Zeitplans), aber sobald ich es alleine laufen lasse, erhält der Sender sein eigenes Signal (obwohl er es blockiert hat ..?) Und keines der andere Threads werden jemals geplant.
Irgendwelche Ideen, was könnte falsch sein? Ich habe versucht, sigqueue
anstelle von raise
zu verwenden, die Signalmaske zu untersuchen und sleep
überall hinzuzufügen, um sicherzustellen, dass die Threads geduldig auf ihre Signale usw. warten, und jetzt bin ich ratlos.
Bearbeiten: Dank der Antwort von psmears glaube ich, das Problem zu verstehen. Hier ist eine mögliche Lösung. Feedback wäre großartig:
num_threads
-Signale an den Prozess und entsperrt dann das Signal für sich selbst. num_threads
ist, um zurückzukehren. num_threads
erreicht, und gibt dann die Sperre frei. Eine mögliche Sorge ist, dass die Signale nicht in die Warteschlange gestellt werden, wenn der Kernel nicht genügend Arbeitsspeicher hat (Linux scheint dieses Problem zu haben). Weißt du, ob sigqueue
den Anrufer zuverlässig informiert, wenn er das Signal nicht in eine Warteschlange stellen kann (in diesem Fall würde ich eine Schleife machen, bis es erfolgreich ist), oder könnten Signale möglicherweise stillschweigend verloren gehen?
Bearbeiten 2: Es scheint jetzt zu funktionieren. Gemäß der Dokumentation für sigqueue
wird EAGAIN
zurückgegeben, wenn das Signal nicht in die Warteschlange gestellt wird. Aber aus Gründen der Robustheit habe ich beschlossen, sigqueue
immer wieder aufzurufen, bis num_threads-1
signal handlers läuft, und Aufrufe nach sched_yield
verschachtelt, nachdem ich num_threads-1
signals gesendet habe.
Zum Zeitpunkt der Thread-Erstellung gab es eine Racebedingung, die neue Threads zählt, aber ich habe sie mit einer seltsamen (ab) Verwendung von Lese-Schreib-Sperren gelöst. Die Thread-Erstellung ist "Lesen" und das Broadcast-Signal ist "Schreiben". Wenn also kein Thread versucht zu senden, wird kein Konflikt bei der Thread-Erstellung erzeugt.
raise()
sendet das Signal (nur) an den aktuellen Thread, so dass andere Threads es nicht empfangen. Ich vermute, dass die Tatsache, dass strace
die Dinge zum Laufen bringt, ein Fehler in strace
ist (aufgrund der Art und Weise, wie es funktioniert, fängt es alle Signale ab, die an den Prozess gesendet werden, und erhöht sie dann wieder auf die falsche Art ...).
Sie können wahrscheinlich mit kill(getpid(), <signal>)
umgehen, um das Signal als Ganzes an den aktuellen Prozess zu senden.
Ein anderes potentielles Problem, das Sie möglicherweise sehen, ist, dass sigpending()
anzeigen kann, dass das Signal für den Prozess aussteht, bevor alle Threads es empfangen haben - das bedeutet, dass mindestens ein solches Signal für den Prozess ansteht. und es ist noch keine CPU verfügbar, um einen Thread zum Ausliefern auszuführen ...
Können Sie näher beschreiben, was Sie erreichen möchten? Und wie tragbar soll es sein? Es gibt fast sicher einen besseren Weg, es zu tun (Signale sind fast immer ein großer Kopfschmerz, besonders wenn sie mit Fäden gemischt werden ...)
Vorausgesetzt, dass Sie die Thread-Erstellung und -Zerstörung scheinbar sperren können, könnte der Thread "broadcasting" nicht nur die erforderlichen Aktualisierungen für Thread-local-state in einer Thread-Warteschlange bereitstellen, die jeder Thread überprüft, wenn er verwendet wird der Thread-Local-State? Wenn es noch Updates gibt, wendet es sie zuerst an.
Sie versuchen, eine Reihe von Threads zu synchronisieren. Aus Sicht des Entwurfsmusters wäre die native pthread-Lösung für Ihr Problem eine Pthread-Barriere.
Tags und Links c multithreading signals pthreads posix