rust 中看似非常简单操作,竟然导致段错误

bli22ard · 2024-12-11 11:26:24 · 419 次点击

环境

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"]}

复现方法

main.rs


#[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👎️

举报· 419 次点击
登录 注册 站外分享
3 条回复  
aloxaf 小成 2024-12-11 12:01:07
issue 里和 stackoverflow 里不都说了么,glibc 压根不支持静态链接,尤其是 gethostbyname 。 想静态链接就用 musl ,ssl 切换到 rustls 。
dilfish 小成 2024-12-11 12:10:14
这个问题我遇到过,你想静态编译 redis 也会警告。 go 是自己写了一套,rust 也有对应的库,
wolfsun 小成 2024-12-11 12:12:21
同意楼上,楼主非要踩一捧一,在智商这一点,狗👍️践踏楼主👎️
返回顶部