From a183c3d599aded9f36141b0ed8dcfe2ed3f86c6d Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 7 Jul 2026 15:27:13 +0200 Subject: [PATCH] fix: take FFI_ArrowArrayStream errno values from libc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The errno constants in ffi_stream.rs were hardcoded to a single set of values, but ENOSYS is 78 only on macOS/iOS and the BSDs — on Linux it is 38, on Windows 40, on Solaris/illumos 89. On WASI even the other codes differ (EINVAL is 28, EIO 29, ENOMEM 48), since WASI numbers its errnos independently. A stream exported on Linux therefore reported ArrowError::NotYetImplemented as 78, which Linux errno tables read as an unrelated code, confusing C consumers that interpret the returned errno. Take the constants from libc instead, as an optional dependency of the ffi feature. It is target-gated off wasm32-unknown-unknown — the one target without a libc — where no OS interprets the codes anyway, so hardcoded Linux values remain. Signed-off-by: Fredrik Fornwall --- Cargo.lock | 1 + arrow-array/Cargo.toml | 7 ++++++- arrow-array/src/ffi_stream.rs | 13 ++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 32ac99ef1793..02033e914394 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,6 +221,7 @@ dependencies = [ "futures", "half", "hashbrown 0.17.1", + "libc", "num-complex", "num-integer", "num-traits", diff --git a/arrow-array/Cargo.toml b/arrow-array/Cargo.toml index df102c32b0d0..4ec358fe85da 100644 --- a/arrow-array/Cargo.toml +++ b/arrow-array/Cargo.toml @@ -45,6 +45,11 @@ ahash = { version = "0.8", default-features = false, features = ["compile-time-r [target.'cfg(not(target_arch = "wasm32"))'.dependencies] ahash = { version = "0.8", default-features = false, features = ["runtime-rng"] } +# Used by the ffi feature for platform-correct errno values. Excluded on +# wasm32-unknown-unknown, which has no libc. +[target.'cfg(not(all(target_family = "wasm", target_os = "unknown")))'.dependencies] +libc = { version = "0.2", default-features = false, optional = true } + [dependencies] arrow-buffer = { workspace = true } arrow-schema = { workspace = true } @@ -63,7 +68,7 @@ all-features = true [features] async = ["dep:futures"] -ffi = ["arrow-schema/ffi", "arrow-data/ffi"] +ffi = ["arrow-schema/ffi", "arrow-data/ffi", "dep:libc"] force_validate = [] # Enable memory tracking support pool = ["arrow-buffer/pool", "arrow-data/pool"] diff --git a/arrow-array/src/ffi_stream.rs b/arrow-array/src/ffi_stream.rs index 815d7c57605d..9a09c3753dd4 100644 --- a/arrow-array/src/ffi_stream.rs +++ b/arrow-array/src/ffi_stream.rs @@ -74,10 +74,21 @@ use crate::record_batch::{RecordBatch, RecordBatchReader}; type Result = std::result::Result; +// Errno values returned through the C stream interface, taken from libc so they match +// the platform the consumer interprets them against. +#[cfg(not(all(target_family = "wasm", target_os = "unknown")))] +use libc::{EINVAL, EIO, ENOMEM, ENOSYS}; + +// wasm32-unknown-unknown has no libc, and no OS to interpret the codes either — any +// non-zero value works there, so use Linux's. +#[cfg(all(target_family = "wasm", target_os = "unknown"))] const ENOMEM: i32 = 12; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] const EIO: i32 = 5; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] const EINVAL: i32 = 22; -const ENOSYS: i32 = 78; +#[cfg(all(target_family = "wasm", target_os = "unknown"))] +const ENOSYS: i32 = 38; /// ABI-compatible struct for `ArrayStream` from C Stream Interface /// See