5 points par GN⁺ 2025-01-24 | 4 commentaires | Partager sur WhatsApp
  • 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

 
carnoxen 2025-01-24

setenv n’est pas thread-safe, et le C ne veut pas corriger cela

La fonction setenv fait encore des siennes.

 
y15un 2025-01-24

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 ». :)

 
halfenif 2025-01-24

J’ai bien compris avec certitude.

 
GN⁺ 2025-01-24
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

    • Dans la bibliothèque standard de Rust, set_var et remove_var nécessiteront un bloc unsafe {} dans l’édition 2024
    • La documentation actuelle mentionne déjà le problème de sécurité, mais le fait d’avoir rendu ces fonctions sûres à l’origine était une erreur
  • Un patch pour glibc a rendu getenv plus sûr, mais le C permet toujours un accès direct à l’environnement, donc ce n’est pas complètement sûr

    • Les mainteneurs de la bibliothèque standard C hésitent à rendre setenv sûr en multithread, mais au minimum une nouvelle API thread-safe devrait être définie
    • Le mainteneur de musl ne semble pas convaincu que ce problème soit impossible à résoudre
  • Rencontrer des bugs liés à l’environnement sous Linux est presque un rite de passage

    • Linus et le kernel sont pragmatiques pour corriger les bugs POSIX, mais glibc reste encore à la traîne
    • Fournir getenv_r(), le synchroniser avec setenv() et émettre des avertissements à la compilation/à l’édition de liens aurait aidé à résoudre le problème
  • La configuration via des variables d’environnement faisait partie du mouvement « 12-factor app », mais cela paraît être une approche absurde

    • Mieux vaudrait utiliser des fichiers de configuration comme YAML plutôt que des variables d’environnement
  • Les machines de CI exécutées sur Amazon AWS ont l’avantage de fournir un véritable utilisateur root

    • On a l’impression d’avoir perdu la capacité de compiler et déboguer du code en local, sans cloud ni conteneurs
  • C’est un excellent article qui dissèque un bug peu intuitif

    • Ce type de compte rendu détaillé de dépannage offre l’expérience la plus proche de le faire soi-même
  • env::set_var n’est désormais plus sûr

    • Il peut être appelé sans risque dans un programme mono-thread
    • Sous Windows, il est toujours sûr, dans les programmes mono-thread comme multithread
    • Dans les programmes multithread sur les autres systèmes d’exploitation, la seule option sûre est de ne pas utiliser set_var ni remove_var
  • Cela rappelle une expérience où setproctitle ne fonctionnait pas dans certaines bases de code

    • Après l’import de numpy, setproctitle ne fonctionnait plus, car l’adresse de environ avait changé à cause d’un appel à getenv ou setenv pendant l’initialisation de numpy