环境
windows wsl DISTRIB_ID=Ubuntu DISTRIB_RELEASE=20.04 DISTRIB_CODENAME=focal DISTRIB_DESCRIPTION="Ubuntu 20.04.6 LTS arch x86_64 rust version stable-x86_64-unknown-linux-gnu (default) rustc 1.83.0 (90b35a623 2024-11-26) Cargo.toml
[package] name = "demo" version = "0.1.0" edition = "2021" [dependencies] reqwest = {version = "0.11",default-features = false,features = ["rustls-tls"]} tokio = {version = "1.42",features = ["full"]} 复现方法
#[tokio::main] async fn main() { let mut tasks=vec![]; for _i in 0..2{ let t=tokio::spawn(async move { let result=reqwest::get("https://github.com").await; if let Ok(result) = result { println!("{:?}",result.status()); } }); tasks.push(t); } for t in tasks { t.await.expect("Something went wrong"); } } ```bash root@computer1:/demo/# RUSTFLAGS="-Ctarget-feature=+crt-static" cargo run --target x86_64-unknown-linux-gnu root@computer1:/demo/# Segmentation fault 原因
在开启静态链接情况下,该代码会导致段错误。具体导致的原因 hyper#2537
主要是因为"github.com:443".to_socket_addrs(); 并发会导致段错误。
main.rs 这个代码也可以出发这个段错误
use std::net::ToSocketAddrs; #[tokio::main] async fn main() { let mut tasks=vec![]; for _i in 0..2{ let t=tokio::spawn(async move { // let result=reqwest::get("https://github.com").await; // if let Ok(result) = result { // println!("{:?}",result.status()); // } "github.com:443".to_socket_addrs(); }); tasks.push(t); } for t in tasks { t.await.expect("Something went wrong"); } } 更底层的原因是,这位老哥的说的getaddrinfo
个人看法
这意味着你要静态链接,http 或者其他什么涉及到主机名转换并发调用了 getaddrinfo 就会大概率会出现段错误,进程就会直接没了。rust 的静态链接和交叉编译,太菜鸡了。 如果你不使用静态链接,而使用动态链接,那么你最好保证你的开发机器软件包版本和你生产环境的软件版本保持一致,不然动态链接 openssl ,在生成看起来已经安装了 openssl ,但是提示找不到。静态链接这一点,golang践踏 rust
