Es scheint in Rust üblich zu sein, einen Thread zum Blockieren von IO zu spawnen, damit Sie nicht blockierende Kanäle verwenden können:
%Vor% Das Problem besteht darin, dass das erneute Verknüpfen von Threads davon abhängt, dass der erzeugte Thread erkennt, dass das empfangende Ende des Channels gelöscht wurde (d. h. ruft send(..)
returns Err(_)
):
Sie können Dummy-Verbindungen für TcpListener
s herstellen und TcpStream
s über einen Klon beenden, aber diese scheinen wirklich hacky Wege zu sein, solche Threads aufzuräumen, und wie es aussieht, weiß ich nicht einmal von a hack , um einen Thread auszulösen, der bei einem Lesevorgang von stdin
blockiert, um beizutreten.
Wie kann ich Threads wie diese aufräumen, oder ist meine Architektur einfach falsch?
Man kann einen Thread in Windows oder Linux / Unix / POSIX nicht sicher abbrechen, daher ist er in der Rust-Standardbibliothek nicht verfügbar.
Hier ist eine interne Diskussion darüber .
Es gibt viele Unbekannte, die durch gewaltsames Abbrechen von Threads entstehen. Es kann sehr unordentlich werden. Darüber hinaus wird die Kombination von Threads und blockierenden E / A immer mit diesem Problem konfrontiert: Sie benötigen jeden blockierenden E / A-Aufruf, um Timeouts zu haben, damit sie sogar eine Chance haben, zuverlässig unterbrechbar zu sein. Wenn man keinen asynchronen Code schreiben kann, muss man entweder Prozesse verwenden (die eine definierte Grenze haben und vom Betriebssystem zwangsweise beendet werden können, aber offensichtlich mit höheren Anforderungen bezüglich Gewicht und Datenfreigabe verbunden sind) oder blockierungsfreie E / A landen Sie Ihren Thread in einer Ereignisschleife, die unterbrechbar ist.
mio ist für asynchronen Code verfügbar. Tokio ist eine Kiste auf höherer Ebene, die auf mio basiert, was das Schreiben von blockierungsfreiem Async-Code noch einfacher macht.
tldr; Die Dummy-Verbindung könnte der einfachste Weg sein.
(Ich nehme linux as os an.)
listener.incoming () ruft .accept () für den TcpListener in seiner .next () -Methode auf und der thread wird im accept call an das os hängen bleiben. Es kann nach meinem besten Wissen nur durch einen Verbindungsversuch oder ein Signal zurückgebracht werden oder wenn der Socket nicht blockierend eingestellt ist.
signal handling scheint von Rost-Standard-Bibliotheken nicht unterstützt zu werden.
Der Dateideskriptor des Sockets scheint im TcpListener nicht zugänglich zu sein, daher können Sie ihn nicht auf den nicht blockierenden Modus einstellen. Auch dass würde Umfragen implizieren, das könnte eine schlechte Idee sein.
Eine Alternative könnte die Verwendung von mio sein, da es eine Ereignisschleife bereitstellt. Sie können entweder Ihre gesamte Anwendung auf die Ereignisschleife abstimmen und müssen dies nicht tun tun Sie Threads, oder Sie könnten eine Ereignisschleife für jeden Thread verwenden, die blockieren könnte und lass es eine zusätzliche Pfeife hören, damit du es aufwecken kannst schließ dich ab. Der erste ist vielleicht nicht mehr machbar, je nachdem wie Viel Code hast du schon und der zweite klingt nach Overkill.
Tags und Links multithreading rust channel blocking