5 pontos por GN⁺ 2025-01-24 | 4 comentários | Compartilhar no WhatsApp
  • Falha que ocorria apenas no ARM64

    • Durante a migração do código de I/O de rede do EdgeDB de Python para Rust, surgiu um problema em que os testes falhavam intermitentemente nos runners de CI com ARM64.
    • No início, parecia um deadlock, mas na realidade o processo estava travando e o runner de testes não conseguia detectar isso.
  • Teoria inicial

    • Para entender por que o problema ocorria apenas no ARM64, foi considerada a diferença entre os modelos de memória.
    • Enquanto o modelo de memória da Intel é mais rígido, o ARM tem um modelo de memória mais fraco.
  • Depuração na máquina de CI

    • Foi feita uma conexão direta ao runner ARM64 na AWS para investigar o problema.
    • O processo travou e deixou um core dump, que foi analisado para identificar a causa do problema.
  • Causa real: setenv e getenv

    • setenv não é seguro em ambientes multithread e pode causar travamentos na interação com getenv.
    • Descobriu-se que a reatribuição de variáveis de ambiente era a causa do problema.
  • Ligação com o openssl_probe

    • O problema ocorreu quando o openssl-probe definiu as variáveis de ambiente SSL_CERT_FILE e SSL_CERT_DIR.
    • O travamento aconteceu durante o processo em que o rust-native-tls do Rust definia essas variáveis de ambiente.
  • Por que ocorreu apenas no Linux ARM64

    • O travamento só acontece quando várias condições coincidem, incluindo a quantidade de variáveis de ambiente e falhas de I/O.
  • Solução

    • Foi decidido trocar o backend rust-native-tls/openssl do reqwest por rustls.
    • O projeto Rust pretende tornar inseguras as funções de configuração de ambiente, e o projeto glibc está melhorando a segurança de getenv para threads.

4 comentários

 
carnoxen 2025-01-24

setenv não é thread-safe, e C não quer corrigir isso

A função setenv está causando problemas de novo.

 
y15un 2025-01-24

Eu escreveria o título como: "A insegurança de thread da stdlib de C é algo que nem o Rust, tão seguro assim, consegue remediar". :)

 
halfenif 2025-01-24

Entendi com certeza.

 
GN⁺ 2025-01-24
Comentários no Hacker News
  • O Rust pretende tornar os manipuladores de ambiente inseguros na próxima edição. Isso pode afetar crates que entrem em conflito

    • Na biblioteca padrão do Rust, set_var e remove_var exigirão o uso de um bloco unsafe {} na edição de 2024
    • A documentação atual menciona os problemas de segurança, mas originalmente foi um erro tornar essas funções seguras
  • Um patch para a glibc tornou getenv mais seguro, mas C ainda permite acesso direto ao ambiente, então continua não sendo totalmente seguro

    • Os mantenedores da biblioteca padrão de C relutam em tornar setenv seguro para multithreading, mas no mínimo uma nova API thread-safe deveria ser definida
    • O mantenedor do musl não está convencido de que esse problema não possa ser resolvido
  • Passar por bugs relacionados ao ambiente no Linux é visto quase como um rito de passagem

    • Linus e o kernel são pragmáticos ao corrigir bugs do POSIX, mas a glibc ainda está atrás
    • Fornecer getenv_r(), sincronizá-lo com setenv() e emitir avisos em tempo de compilação/linkedição teria ajudado a resolver o problema
  • Configuração usando variáveis de ambiente fazia parte do movimento "12-factor app", mas isso parece um método tolo

    • Em vez de variáveis de ambiente, usar arquivos de configuração como YAML parece uma abordagem melhor
  • Máquinas de CI executadas na Amazon AWS têm a vantagem de fornecer um usuário root real

    • Parece que perdemos a capacidade de compilar e depurar código localmente sem nuvem nem containers
  • É um ótimo artigo investigando um bug nada intuitivo

    • Relatos detalhados de troubleshooting como este oferecem a experiência mais próxima de fazer isso na prática
  • env::set_var agora é inseguro

    • Em programas single-thread, ele pode ser chamado com segurança
    • No Windows, ele é sempre seguro tanto em programas single-thread quanto multithread
    • Em programas multithread de outros sistemas operacionais, a única escolha segura é não usar set_var nem remove_var
  • Isso relembra a experiência de setproctitle não funcionar em uma determinada base de código

    • Depois de importar numpy, setproctitle não funcionava, porque o endereço de environ mudou devido a chamadas de getenv ou setenv durante a inicialização do numpy