-
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
setenvnão é thread-safe, e C não quer corrigir issoA função
setenvestá causando problemas de novo.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". :)
Entendi com certeza.
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
set_vareremove_varexigirão o uso de um blocounsafe {}na edição de 2024Um patch para a glibc tornou
getenvmais seguro, mas C ainda permite acesso direto ao ambiente, então continua não sendo totalmente segurosetenvseguro para multithreading, mas no mínimo uma nova API thread-safe deveria ser definidaPassar por bugs relacionados ao ambiente no Linux é visto quase como um rito de passagem
getenv_r(), sincronizá-lo comsetenv()e emitir avisos em tempo de compilação/linkedição teria ajudado a resolver o problemaConfiguração usando variáveis de ambiente fazia parte do movimento "12-factor app", mas isso parece um método tolo
Máquinas de CI executadas na Amazon AWS têm a vantagem de fornecer um usuário root real
É um ótimo artigo investigando um bug nada intuitivo
env::set_varagora é inseguroset_varnemremove_varIsso relembra a experiência de
setproctitlenão funcionar em uma determinada base de códigonumpy,setproctitlenão funcionava, porque o endereço de environ mudou devido a chamadas degetenvousetenvdurante a inicialização donumpy