rust2go icon indicating copy to clipboard operation
rust2go copied to clipboard

cannot find value SOCK_CLOEXEC in crate libc; cannot find value SOCK_NONBLOCK in crate libc

Open powerttt opened this issue 4 months ago • 0 comments

在 macOS 上运行 example-monoio-mem 时遇到的问题及解决方案

环境信息

  • 操作系统:macOS 15.0 (24A335)
  • Rust 版本:rustc 1.81.0 (eeb90cda1 2024-09-04) (Homebrew)

问题描述

在 macOS 上克隆并运行项目时,examples/example-monoio 可以正常运行,但 examples/example-monoio-mem 出现编译错误。错误信息如下:

error[E0425]: cannot find value SOCK_CLOEXEC in crate libc
error[E0425]: cannot find value SOCK_NONBLOCK in crate libc

这个问题是由于 macOS 上 libc crate 中缺少 SOCK_CLOEXECSOCK_NONBLOCK 常量导致的。

解决方案

修改 mem-ring/src/eventfd.rs 文件,使用条件编译来处理不同平台的差异。以下是修改后的代码:

use std::{
    cell::UnsafeCell,
    io::Error,
    os::unix::io::{AsRawFd, FromRawFd, RawFd},
};

#[cfg(feature = "monoio")]
use monoio::{buf::RawBuf, io::AsyncReadRent, net::UnixStream};

#[cfg(all(feature = "tokio", not(feature = "monoio")))]
use tokio::{io::AsyncReadExt, net::UnixStream};

pub(crate) fn new_pair() -> Result<(RawFd, RawFd), Error> {
    let mut fds = [-1; 2];
    let mut flags = libc::SOCK_STREAM;

    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        flags |= libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
    }

    if unsafe {
        libc::socketpair(
            libc::AF_UNIX,
            flags,
            0,
            fds.as_mut_ptr(),
        )
    } == -1
    {
        return Err(Error::last_os_error());
    }

    #[cfg(not(any(target_os = "linux", target_os = "android")))]
    {
        for &fd in &fds {
            unsafe {
                // 设置非阻塞
                let flags = libc::fcntl(fd, libc::F_GETFL);
                libc::fcntl(fd, libc::F_SETFL, flags | libc::O_NONBLOCK);
                
                // 设置 CLOEXEC
                libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC);
            }
        }
    }

    Ok((fds[0], fds[1]))
}

这个修改使用条件编译来处理 Linux/Android 和其他 Unix 系统(如 macOS)之间的差异。对于 Linux 和 Android,直接在 socketpair 调用中使用 SOCK_NONBLOCKSOCK_CLOEXEC 标志。对于其他系统,在创建套接字后使用 fcntl 来设置非阻塞模式和 CLOEXEC 标志。

验证

在进行上述修改后,examples/example-monoio-mem 可以在 macOS 上成功编译和运行。

建议

考虑将这个修改合并到主分支,以提高项目在不同 Unix 系统上的兼容性。同时,可以在文档中注明这个平台差异,以帮助其他可能遇到类似问题的开发者。

由于Rust刚入门,此Issue来自AI总结,如有问题请及时更正

powerttt avatar Oct 14 '24 07:10 powerttt