Auswahl am UDP-Socket endet nicht, wenn der Socket geschlossen ist - was mache ich falsch?

8

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.

    
Michael Kohne 19.01.2009, 18:07
quelle

6 Antworten

4

Vielleicht solltest du etwas anderes benutzen, um die Auswahl aufzuwecken. Vielleicht eine Pfeife oder so.

    
iny 26.01.2009, 19:54
quelle
4

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.

    
John Zwinck 19.01.2009 18:25
quelle
3

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.

    
Richard Whitty 27.07.2009 10:15
quelle
2

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.

    
a2800276 22.01.2009 10:34
quelle
2

Ich würde sagen, der Unterschied ist, dass recvfrom aktiv versucht, eine Nachricht von einem einzelnen Socket zu lesen, wo select darauf wartet, dass eine Nachricht ankommt, möglicherweise auf mehreren Handles und nicht unbedingt Socket-Handles.

    
Rob K 26.01.2009 19:46
quelle
0

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:

  1. Der Thread ruft select auf, wird aber nicht geplant.
  2. Sie schließen den Socket.
  3. In einem Thread, von dem Ihr Code nichts weiß (vielleicht ist es Teil der internen Speicherverwaltung oder der internen Protokollierung der Plattform), öffnet eine Bibliothek einen Socket und erhält dieselbe ID wie der Socket, den Sie geschlossen haben.
  4. Der Thread geht jetzt in select , aber es ist select ing für den Socket, der von der Bibliothek geöffnet wurde.
  5. Katastrophenstreiks.

Sie dürfen nicht versuchen, eine Ressource freizugeben, während ein anderer Thread sie verwendet oder verwenden könnte.

    
David Schwartz 24.01.2017 18:51
quelle