-
Ein Absturz, der nur auf ARM64 auftrat
- Beim Portieren des Netzwerk-I/O-Codes von EdgeDB von Python nach Rust trat das Problem auf, dass Tests auf ARM64-CI-Runnern gelegentlich fehlschlugen.
- Zunächst sah es wie ein Deadlock aus, tatsächlich stürzte jedoch der Prozess ab, und der Test-Runner erkannte dies nicht.
-
Erste Theorie
- Um zu verstehen, warum das Problem nur auf ARM64 auftrat, wurden Unterschiede im Speichermodell berücksichtigt.
- Das Speichermodell von Intel ist streng, während ARM ein schwächeres Speichermodell hat.
-
Debugging auf der CI-Maschine
- Über AWS wurde direkt eine Verbindung zu einem ARM64-Runner hergestellt, um das Problem zu untersuchen.
- Der Prozess stürzte ab und hinterließ einen Core Dump, der untersucht wurde, um die Ursache des Problems zu ermitteln.
-
Die tatsächliche Ursache: setenv und getenv
setenv ist in einer Multithread-Umgebung nicht sicher und kann im Zusammenspiel mit getenv Abstürze verursachen.
- Es stellte sich heraus, dass die Neuzuweisung von Umgebungsvariablen die Ursache des Problems war.
-
Die Verbindung zu openssl-probe
- Das Problem trat auf, als
openssl-probe die Umgebungsvariablen SSL_CERT_FILE und SSL_CERT_DIR setzte.
- Beim Setzen dieser Umgebungsvariablen durch Rusts
rust-native-tls kam es zum Absturz.
-
Warum es nur auf ARM64 Linux auftrat
- Der Absturz tritt nur auf, wenn mehrere Bedingungen gleichzeitig erfüllt sind; dazu gehören die Anzahl der Umgebungsvariablen und I/O-Fehler.
-
Lösung
- Es wurde beschlossen, im
rust-native-tls/openssl-Backend von reqwest auf rustls umzusteigen.
- Das Rust-Projekt plant, Funktionen zur Umgebungskonfiguration als unsafe zu markieren, und das glibc-Projekt verbessert die Thread-Sicherheit von
getenv.
4 Kommentare
setenvist nicht threadsicher, und C möchte das nicht ändernDie Funktion
setenvmacht schon wieder Ärger.Ich würde den Titel als „Die Thread-Unsicherheit der C-Stdlib kann nicht einmal das ach so sichere Rust retten“ schreiben. :)
Ich habe es definitiv verstanden.
Hacker-News-Kommentar
In der nächsten Rust-Edition sollen Umgebungsvariablen-Setter als unsicher eingestuft werden. Das könnte Crates betreffen, die Konflikte auslösen
set_varundremove_varin der Edition 2024 innerhalb einesunsafe {}-Blocks verwendet werdenEin Patch für glibc hat
getenvsicherer gemacht, aber C erlaubt weiterhin direkten Zugriff auf die Umgebung und ist daher nicht vollständig sichersetenvthreadsicher zu machen, aber zumindest sollte eine neue threadsichere API definiert werdenUnter Linux auf umgebungsbezogene Bugs zu stoßen, gilt fast als eine Art Initiationsritus
getenv_r()bereitzustellen, es mitsetenv()zu synchronisieren und beim Kompilieren/Linken Warnungen auszugeben, hätte bei der Lösung des Problems helfen könnenKonfiguration über Umgebungsvariablen war Teil der „12-factor app“-Bewegung, aber ich halte das für einen törichten Ansatz
CI-Maschinen, die auf Amazon AWS laufen, haben den Vorteil, dass sie echte Root-Benutzer bereitstellen
Ein großartiger Artikel, der einem nicht offensichtlichen Bug auf den Grund geht
env::set_varist jetzt unsicherset_varoderremove_varnicht zu verwendenEs erinnert an die Erfahrung, dass
setproctitlein bestimmten Codebasen nicht funktioniertenumpyfunktioniertesetproctitlenicht mehr, weil sich durch einen Aufruf vongetenvodersetenvwährend dernumpy-Initialisierung die Adresse von environ geändert hatte