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

19 小时 12 分钟前
 bli22ard

环境

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

1816 次点击
所在节点    程序员
16 条回复
aloxaf
18 小时 37 分钟前
issue 里和 stackoverflow 里不都说了么,glibc 压根不支持静态链接,尤其是 gethostbyname 。

想静态链接就用 musl ,ssl 切换到 rustls 。
dilfish
18 小时 28 分钟前
这个问题我遇到过,你想静态编译 redis 也会警告。

go 是自己写了一套,rust 也有对应的库,
wolfsun
18 小时 26 分钟前
同意楼上,楼主非要踩一捧一,在智商这一点,狗👍️践踏楼主👎️
virusdefender
17 小时 16 分钟前
glibc 根本不能静态链接,有些里面的函数你用到的时候还会动态寻找其他的 so ,比如一些密码类的
hingle
16 小时 59 分钟前
OP 就是专门踩 rust 捧 go 的。https://v2ex.com/t/1090526
bli22ard
16 小时 57 分钟前
@aloxaf
我测试了一下,musl 静态链接这个代码确实没有问题。linux 静态链接还是得 musl 。
@dilfish 下次可以试试 musl 静态链接


@virusdefender 看来 glibc 确实是不能静态链接。即使静态链接编译成功也是假象,段错误在运行时等着。
bli22ard
16 小时 55 分钟前
@wolfsun 上来就开喷,不进行一下准备工作吗?比如列一丁点事实?
bli22ard
16 小时 47 分钟前
@hingle 列的都是客观事实
adoal
16 小时 35 分钟前
glibc 大毒瘤
dogfeet
15 小时 52 分钟前
我都是:

不使用 native-tls ,专用 rustls
使用 cargo zigbuild ,还可以指定 glibc 版本,挺无脑的,没你说的那么费劲。
dogfeet
15 小时 47 分钟前
对了,刚忘说了,我是直接在 windows 上交叉编译 linux 的。安装下 ziglang 和 zigbuild 就行了。
没觉得比 Golang 麻烦在哪里。
kagenomirai
15 小时 31 分钟前
OP 说的也不算事实。链接不是 rust 的责任。你换了 C C++ 或者 D 你都得链接一个 libc ,除非你不调系统的 api 或者有一层 vm 的包装。而 glibc 众所周知是不可以静态链接的。rust 这类系统级编程语言是不可能脱离 c 的 api ,顶多帮你做一些 dirty work ,到头来免不了做系统层面上的兼容。所有 OP 拿 go 和 rust 比就好像拿 lua 和 c 比一样,都不是同一个类语言,在设计上解决的问题也不同。
归根结底,比较两个(针对某一问题设计的)语言根本没有意义。比较锤子和螺丝刀有意义吗?
bli22ard
15 小时 2 分钟前
@adoal 感觉有点道理


@dogfeet cargo zigbuild 没试过,我是用 https://github.com/cross-rs/cross 交叉编译。zigbuild 不静态链接,到运行的机器容易提示找不到对应 so 吧?静态链接,最佳实战应该就是 musl 了。



@kagenomirai
glibc 众所周知是不可以静态链接的,这个我见识短,之前不知道。
和 lua 比不合适,lua 需要依赖解释器。rust 和 golang 编译输出都是可执行程序,所以它们比较有可比性。编译和链接这块 golang 难道不比 rust 方便? go buid 指定 os 和 arch ,就可以了。
dogfeet
14 小时 52 分钟前
@bli22ard 是的,想要不依赖 glibc 就用 musl ,想要不依赖 openssl ,就是用 rustls 。
至于要方便的交叉编译,直接使用 cargo zigbuild 就行。

大致就是这么简单。
dogfeet
14 小时 46 分钟前
@dogfeet 我一般还是用 glibc ,但是不用 native-tls(openssl)。虽然很多人说 musl 性能较 musl 差,但其实我并不在乎这个,只是没觉得 glibc 问题有那么严重。毕竟这玩意和内核关系紧密,不像 openssl 。
在加上 zigbuild 能很方便的指定 glibc 的版本,没觉得这个有啥麻烦的地方。所以继续 glibc
bli22ard
12 小时 34 分钟前
@dogfeet zigbuild 我试了下,使用 rustls , 指定低版本的 glibc ,比如 2.22 ,那大多数服务器都可以兼容,不知道这样做有没有什么坏处

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1096658

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX