From 3fa016dfdd7946e63f87da0c25b2e58a7b6dd258 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 10 May 2026 03:03:40 +0300 Subject: [PATCH] os: gc fix in fd_read --- vlib/os/fd.c.v | 20 +++++++++++++++++++- vlib/os/os_nix.c.v | 9 ++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/vlib/os/fd.c.v b/vlib/os/fd.c.v index c0a0984a4..7580e50da 100644 --- a/vlib/os/fd.c.v +++ b/vlib/os/fd.c.v @@ -56,13 +56,31 @@ pub fn fd_slurp(fd int) []string { } // fd_read reads data from the file descriptor. It returns the read data, and how many bytes were read. +// On signal interruption (EINTR), the read is retried so callers do not see spurious empty results +// when a signal (for example a Boehm GC stop-the-world signal in a multi-threaded program) interrupts +// a blocking read. pub fn fd_read(fd int, maxbytes int) (string, int) { if fd == -1 { return '', 0 } unsafe { mut buf := malloc_noscan(maxbytes + 1) - nbytes := int(C.read(fd, buf, maxbytes)) + mut nbytes := 0 + for { + $if !windows { + C.errno = 0 + } + nbytes = int(C.read(fd, buf, maxbytes)) + if nbytes >= 0 { + break + } + $if !windows { + if C.errno == C.EINTR { + continue + } + } + break + } if nbytes < 0 { free(buf) return '', nbytes diff --git a/vlib/os/os_nix.c.v b/vlib/os/os_nix.c.v index 73e19cdc2..4d2a58d74 100644 --- a/vlib/os/os_nix.c.v +++ b/vlib/os/os_nix.c.v @@ -340,7 +340,14 @@ pub fn execute(cmd string) Result { soutput := fd_slurp(read_fd).join('') fd_close(read_fd) mut status := 0 - if C.waitpid(pid, &status, 0) == -1 { + for { + C.errno = 0 + if C.waitpid(pid, &status, 0) != -1 { + break + } + if C.errno == C.EINTR { + continue + } return Result{ exit_code: -1 output: soutput -- 2.39.5