-
Un crash survenant uniquement sur ARM64
- Lors du portage du code d’E/S réseau d’EdgeDB de Python vers Rust, un problème est apparu : les tests échouaient de manière intermittente sur les runners CI ARM64.
- Au départ, cela ressemblait à un deadlock, mais en réalité le processus plantait et le runner de tests ne le détectait pas.
-
Hypothèse initiale
- Pour comprendre pourquoi le problème ne survenait que sur ARM64, les différences de modèle mémoire ont été prises en compte.
- Le modèle mémoire d’Intel est strict, tandis qu’ARM dispose d’un modèle mémoire plus faible.
-
Débogage sur la machine CI
- Une connexion directe au runner ARM64 sur AWS a permis d’enquêter sur le problème.
- Le processus a planté en laissant un core dump, dont l’analyse a permis d’identifier la cause du problème.
-
La vraie cause : setenv et getenv
setenv n’est pas sûr en environnement multithread et peut provoquer des crashs dans ses interactions avec getenv.
- La réaffectation de variables d’environnement s’est révélée être la cause du problème.
-
Le lien avec openssl_probe
- Le problème se produisait lorsque
openssl-probe définissait les variables d’environnement SSL_CERT_FILE et SSL_CERT_DIR.
- Le crash survenait pendant le processus par lequel
rust-native-tls de Rust définissait ces variables d’environnement.
-
Pourquoi uniquement sur ARM64 Linux
- Le crash ne se produit que si plusieurs conditions sont réunies, notamment le nombre de variables d’environnement et des échecs d’E/S.
-
Solution
- Il a été décidé de passer du backend
rust-native-tls/openssl de reqwest à rustls.
- Le projet Rust prévoit de rendre les fonctions de configuration de l’environnement non sûres, tandis que le projet glibc améliore la sûreté vis-à-vis des threads de
getenv.
4 commentaires
setenvn’est pas thread-safe, et le C ne veut pas corriger celaLa fonction
setenvfait encore des siennes.J’écrirais le titre ainsi : « L’absence de sûreté des threads dans la stdlib C, un échec que même Rust, pourtant sûr, ne peut pas sauver ». :)
J’ai bien compris avec certitude.
Commentaire Hacker News
La prochaine édition de Rust va rendre les mutateurs d’environnement non sûrs. Cela pourrait affecter des crates qui provoquent des conflits
set_varetremove_varnécessiteront un blocunsafe {}dans l’édition 2024Un patch pour glibc a rendu
getenvplus sûr, mais le C permet toujours un accès direct à l’environnement, donc ce n’est pas complètement sûrsetenvsûr en multithread, mais au minimum une nouvelle API thread-safe devrait être définieRencontrer des bugs liés à l’environnement sous Linux est presque un rite de passage
getenv_r(), le synchroniser avecsetenv()et émettre des avertissements à la compilation/à l’édition de liens aurait aidé à résoudre le problèmeLa configuration via des variables d’environnement faisait partie du mouvement « 12-factor app », mais cela paraît être une approche absurde
Les machines de CI exécutées sur Amazon AWS ont l’avantage de fournir un véritable utilisateur root
C’est un excellent article qui dissèque un bug peu intuitif
env::set_varn’est désormais plus sûrset_varniremove_varCela rappelle une expérience où
setproctitlene fonctionnait pas dans certaines bases de codenumpy,setproctitlene fonctionnait plus, car l’adresse de environ avait changé à cause d’un appel àgetenvousetenvpendant l’initialisation denumpy