net: harden epoll-wait against EINTR + EDN improper-list write
ober
95f42c95ca06b6553dc5e2cafe79c766a970ff9d
--- a/jerboa-native-rs/src/epoll.rs +++ b/jerboa-native-rs/src/epoll.rs @@ -55,16 +55,21 @@ pub extern "C" fn jerboa_epoll_wait( libc::epoll_event { events: 0, u64: 0 }; max_events as usize ]; - let n = unsafe { - libc::epoll_wait(epfd, events.as_mut_ptr(), max_events, timeout_ms) + let n = loop { + let r = unsafe { + libc::epoll_wait(epfd, events.as_mut_ptr(), max_events, timeout_ms) + }; + if r < 0 { + let err = std::io::Error::last_os_error(); + if err.raw_os_error() == Some(libc::EINTR) { + // Interrupted by signal — retry transparently. + continue; + } + crate::panic::set_last_error(format!("epoll_wait: {}", err)); + return -1; + } + break r; }; - if n < 0 { - crate::panic::set_last_error(format!( - "epoll_wait: {}", - std::io::Error::last_os_error() - )); - return -1; - } // Copy results to output buffer: each entry is (fd:i32, events:u32) = 8 bytes let out = unsafe { std::slice::from_raw_parts_mut(events_out, (max_events as usize) * 8) --- a/jerboa-native-rs/src/lib.rs +++ b/jerboa-native-rs/src/lib.rs @@ -39,9 +39,9 @@ mod wasm; #[cfg(feature = "spidermonkey")] mod wasm_sm; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "linux", target_os = "android"))] mod epoll; -#[cfg(all(target_os = "linux", feature = "tls"))] +#[cfg(all(any(target_os = "linux", target_os = "android"), feature = "tls"))] mod http_parse; #[cfg(target_os = "linux")] mod inotify_native; --- a/lib/std/net/io.sls +++ b/lib/std/net/io.sls @@ -222,7 +222,11 @@ (when (io-poller-running? poller) ;; Block until events (or wakefd signal). ;; Use 100ms timeout as safety net so we re-check running?. - (let ([events (epoll-wait epfd *max-events* 100)]) + ;; epoll_wait can return -1/EINTR on Termux when a signal + ;; arrives mid-syscall; treat that as an empty event list and + ;; re-enter the loop instead of letting the poller die. + (let ([events (guard (exn [#t '()]) + (epoll-wait epfd *max-events* 100))]) (for-each (lambda (ev) (let ([fd (car ev)] --- a/lib/std/text/edn.sls +++ b/lib/std/text/edn.sls @@ -323,10 +323,18 @@ (define (write-edn-list lst port) (put-char port #\() (let loop ([l lst] [first? #t]) - (unless (null? l) - (unless first? (put-char port #\space)) - (write-edn (car l) port) - (loop (cdr l) #f))) + (cond + [(null? l) (void)] + [(pair? l) + (unless first? (put-char port #\space)) + (write-edn (car l) port) + (loop (cdr l) #f)] + [else + ;; Improper / dotted pair: emit final element as if it were the + ;; second member of a 2-list. Lossy for cons cells with non-list + ;; cdrs, but keeps EDN spec-compliant and avoids a crash. + (unless first? (put-char port #\space)) + (write-edn l port)])) (put-char port #\))) (define (write-edn-vector vec port)