Ich arbeite an einem Linux System (Ubuntu 7.04 Server mit einem 2.6.20 Kernel).
Ich habe ein Programm, bei dem ein Thread (thread1) auf eine Auswahl wartet, damit ein UDP-Socket lesbar wird. Ich verwende das select (mit meinem Socket als single reefd und dem single exceptfd) statt nur recvfrom aufzurufen, weil ich ein Timeout haben möchte.
Von einem anderen Thread, ich schließe und schließe den Socket. Wenn ich dies tue, während Thread 1 in einem recvfrom blockiert ist, wird der recvfrom sofort beendet. Wenn ich dies tue, während thread1 bei einer Auswahl mit einem Timeout blockiert ist, wird die Auswahl NICHT sofort beendet, sondern wird schließlich korrekt ablaufen.
Kann mir jemand sagen, warum die Auswahl nicht beendet wird, sobald der Sockel geschlossen ist? Ist das nicht eine Ausnahme? Ich kann sehen, wo es (offensichtlich) nicht lesbar ist, aber es ist geschlossen, was außergewöhnlich zu sein scheint.
Hier ist die Öffnung des Sockets (alle Fehlerbehandlung entfernt, um die Dinge einfach zu halten):
%Vor%Hier ist die Select-Anweisung, die thread1 ausführt:
%Vor%UPDATE: Offensichtlich (wie unten angegeben) ist das Schließen des Sockets keine Ausnahmebedingung (aus Sicht der Auswahl). Ich denke, was ich wissen muss ist: Warum? Und, ist das beabsichtigt ?.
Ich möchte wirklich das Denken hinter diesem ausgewählten Verhalten verstehen, weil es meinen Erwartungen widerspricht. Daher muss ich natürlich meine Denkweise anpassen, wie der TCP-Stack funktioniert. Bitte erkläre es mir.
UDP ist ein verbindungsloses Protokoll. Da keine Verbindung besteht, kann keine unterbrochen werden, so dass der Verbraucher nicht weiß, dass der Hersteller nie wieder senden wird.
Sie können veranlassen, dass der Producer eine "End of Stream" -Nachricht sendet und der Consumer beim Empfang beendet wird.
Konnten Sie kein Signal (z. B. USR2) an den Thread senden, was bewirken würde, dass select () mit EINTR zurückkehrt? Setzen Sie dann im Signal-Handler ein Flag, das besagt, dass die select () nicht neu gestartet werden soll?
Das würde die Notwendigkeit des Wartens auf mehrere Dateideskriptoren beseitigen und scheint viel sauberer zu sein als die Verwendung einer Pipe, um sie zu töten.
Ich denke, die naheliegendste Lösung ist, dass das Schließen nicht als Ausnahmezustand betrachtet wird. Ich denke, die Wurzel des Problems ist, dass Sie die Philosophie von select
nicht wirklich verstehen. Warum um alles in der Welt tüftelst du mit der Steckdose in einem anderen Thread herum, das klingt wie ein Rezept für ein Desaster.
Ihr Code ist grundlegend gebrochen. Variationen über diesen Fehler sind häufig und haben in der Vergangenheit zu schwerwiegenden Fehlern mit massiven Auswirkungen auf die Sicherheit geführt. Hier ist, was Sie vermissen:
Wenn Sie den Socket schließen, gibt es einfach keine Möglichkeit zu wissen, ob der andere Thread in select
blockiert ist oder in select
blockiert werden soll. Betrachten Sie beispielsweise Folgendes:
select
auf, wird aber nicht geplant. select
, aber es ist select
ing für den Socket, der von der Bibliothek geöffnet wurde. Sie dürfen nicht versuchen, eine Ressource freizugeben, während ein anderer Thread sie verwendet oder verwenden könnte.
Tags und Links c sockets network-programming unix