Was könnte einen connection.send () blockieren? (aus conn1, conn2 = multiprocessing.Pipe ())

8

Ich bin Debug-Anwendung, die Informationen von 2 Sensoren sammeln: eine Webcam und ein Mikrofon.

Die allgemeine Architektur ist ziemlich einfach:

  • Der Hauptprozess sendet Nachrichten (start, stop, get_data) über Pipes an die untergeordneten Prozesse (jeweils einen).
  • untergeordnete Prozesse sammeln die Daten und senden sie an den Hauptprozess

Kind & amp; Hauptprozesse sind in unendlichen Schleifen, um Befehle zu verarbeiten (der Hauptprozess vom Benutzer, der Kindprozess vom Hauptprozess).

Es funktioniert global, aber ich habe Probleme, die untergeordneten Prozesse zu stoppen.

Ich habe den Code eingeloggt und es scheint 2 Dinge zu passieren:

  1. Die Nachricht 'stop' wird gesendet, kommt aber nicht durch die Pipe.
  2. Der Kindprozess sendet weiterhin Daten und die conn.send (data) Blöcke.

Das Verhalten ist eindeutig mit dem Status der Verbindung verknüpft, da untergeordnete Prozesse, die nichts zurückliefern, dieses Verhalten nicht haben. Dennoch sehe ich nicht, wie man die aktuelle Architektur, die vernünftig erscheint, debuggt / modifiziert.

Also, was verursacht dieses blockierende Verhalten und wie man es vermeidet?

Dies ist der Code, der für jede Iteration der Endlosschleife im Kindprozess ausgeführt wird:

%Vor%

update : Es scheint, dass die Pipe nicht gleichzeitig an beiden Enden geschrieben werden kann. Es funktioniert, wenn Sie die letzten Zeilen des obigen Codes in:

ändern %Vor%

Die Frage bleibt offen, da Pipe standardmäßig als Vollduplex dokumentiert ist und dieses Verhalten überhaupt nicht dokumentiert ist. Ich muss etwas falsch verstanden haben. Bitte, erleuchte mich!

update 2 : Nur um klar zu sein, ist in dieser Situation keine Verbindung geschlossen. Um die Reihenfolge der Ereignisse zu beschreiben:

  • Der Hauptprozess sendet eine Nachricht ("stop") (er leert die Verbindung vor dem Senden der Nachricht)
  • Der Hauptprozess gibt eine (unendliche) Schleife ein, die stoppt, wenn der Kindprozess beendet wird.
  • währenddessen wird der Kindprozess beim Senden blockiert und erhält die Nachricht nie.
LBarret 02.09.2012, 14:52
quelle

1 Antwort

4

Ein Vollduplex multiprocessing.Pipe wird als socketpair() implementiert. Der Aufruf von .send kann für alle normalen Gründe blockieren, wenn mit einem Socket gesprochen wird. Aufgrund Ihrer Beschreibung ist es wahrscheinlich, dass der Leser von Pipe das Lesen beendet hat und sich Daten in den Puffern im Kernel bis zu dem Punkt angesammelt haben, an dem Ihre .send blockiert.

Wenn Sie explizit .close auf der Empfängerseite eingeben, erhalten Sie wahrscheinlich eine Art von Fehler (obwohl möglicherweise auch SIGPIPE , nicht sicher), wenn Sie .send versuchen. Wenn Ihre empfangende Verbindung nicht mehr verfügbar ist, geschieht dies wahrscheinlich automatisch. Sie können das Problem möglicherweise beheben, indem Sie vorsichtiger vorgehen, keine Referenzen (direkt oder indirekt) auf der Empfängerseite zu speichern, damit die Zuordnung aufgehoben wird, wenn dieser Thread nicht mehr vorhanden ist.

Trivial-Demo von blocking .send :

%Vor%

Beachten Sie, dass nach einiger Zeit der Ausdruck "send!" beendet wird.

    
Ben Jackson 05.09.2012 01:20
quelle

Tags und Links