From 22e728b3ca9906a81fbc39f0976d7f628f245d63 Mon Sep 17 00:00:00 2001 From: Yehor Smoliakov Date: Tue, 24 Mar 2026 12:05:37 +0000 Subject: [PATCH] fix a bug in macos --- python/rsloop/__init__.py | 5 ++- src/python_api.rs | 64 +++++++++++++++++++++++++++++++++------ src/stream_transport.rs | 2 +- 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/python/rsloop/__init__.py b/python/rsloop/__init__.py index 3e3d2a7..be8459b 100644 --- a/python/rsloop/__init__.py +++ b/python/rsloop/__init__.py @@ -1159,7 +1159,10 @@ def __windows_command_line_to_argv(cmd: str) -> list[str]: argc = __ctypes.c_int() command_line_to_argv = __ctypes.windll.shell32.CommandLineToArgvW - command_line_to_argv.argtypes = [__ctypes.c_wchar_p, __ctypes.POINTER(__ctypes.c_int)] + command_line_to_argv.argtypes = [ + __ctypes.c_wchar_p, + __ctypes.POINTER(__ctypes.c_int), + ] command_line_to_argv.restype = __ctypes.POINTER(__ctypes.c_wchar_p) argv = command_line_to_argv(cmd, __ctypes.byref(argc)) if not argv: diff --git a/src/python_api.rs b/src/python_api.rs index b24e47c..4458ea1 100644 --- a/src/python_api.rs +++ b/src/python_api.rs @@ -397,6 +397,38 @@ fn build_stream_socket( Ok(sock.unbind()) } +#[cfg(unix)] +fn set_socket_bool_option_unix( + py: Python<'_>, + sock: &Py, + level: libc::c_int, + option: libc::c_int, + enabled: bool, +) -> PyResult<()> { + let fd = fd_ops::fileobj_to_fd(py, sock.bind(py))?; + let fd: libc::c_int = fd + .try_into() + .map_err(|_| PyRuntimeError::new_err("socket file descriptor out of range"))?; + let value: libc::c_int = enabled.into(); + let value_len: libc::socklen_t = std::mem::size_of_val(&value) + .try_into() + .expect("socklen_t can represent c_int size"); + let result = unsafe { + libc::setsockopt( + fd, + level, + option, + (&value as *const libc::c_int).cast(), + value_len, + ) + }; + if result == 0 { + Ok(()) + } else { + Err(PyErr::from(std::io::Error::last_os_error())) + } +} + async fn connect_socket_to_address(sock: Py, address: Py) -> PyResult<()> { let fd = Python::attach(|py| fd_ops::fileobj_to_fd(py, sock.bind(py)))?; match Python::attach(|py| -> PyResult<()> { @@ -524,6 +556,7 @@ fn build_tcp_server_sockets( let sol_socket = socket_mod.getattr("SOL_SOCKET")?; let so_reuseaddr = socket_mod.getattr("SO_REUSEADDR")?; let so_reuseport = socket_mod.getattr("SO_REUSEPORT").ok(); + #[cfg(not(unix))] let so_keepalive = socket_mod.getattr("SO_KEEPALIVE")?; let addrinfos = resolve_stream_addrinfos(py, host, port, family, 0, flags)?; let mut sockets = Vec::with_capacity(addrinfos.len()); @@ -547,15 +580,28 @@ fn build_tcp_server_sockets( } } if let Some(keep_alive) = keep_alive { - sock.call_method1( - py, - "setsockopt", - ( - sol_socket.clone(), - so_keepalive.clone(), - i32::from(keep_alive), - ), - )?; + #[cfg(unix)] + { + set_socket_bool_option_unix( + py, + &sock, + libc::SOL_SOCKET, + libc::SO_KEEPALIVE, + keep_alive, + )?; + } + #[cfg(not(unix))] + { + sock.call_method1( + py, + "setsockopt", + ( + sol_socket.clone(), + so_keepalive.clone(), + i32::from(keep_alive), + ), + )?; + } } sock.call_method1(py, "bind", (sockaddr,))?; sock.call_method1(py, "listen", (backlog,))?; diff --git a/src/stream_transport.rs b/src/stream_transport.rs index b615709..abb667a 100644 --- a/src/stream_transport.rs +++ b/src/stream_transport.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, VecDeque}; use std::fs; use std::io::{self, Read, Write as _}; use std::net::{Shutdown, TcpListener as StdTcpListener, TcpStream as StdTcpStream}; -#[cfg(unix)] +#[cfg(target_os = "linux")] use std::os::fd::{AsRawFd, FromRawFd, OwnedFd}; use std::os::raw::c_int; #[cfg(unix)]