Actually I can avoid the EBADF by checking that the fd is 'live' with something like fstat:
[[[ Index: libguile/posix.c --- libguile/posix.c.orig +++ libguile/posix.c @@ -1325,8 +1325,12 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, static void close_inherited_fds_slow (posix_spawn_file_actions_t *actions, int max_fd) { - while (--max_fd > 2) - posix_spawn_file_actions_addclose (actions, max_fd); + struct stat sb; + max_fd = getdtablecount(); + while (--max_fd > 2) { + if (fstat(max_fd, &sb) != -1) + posix_spawn_file_actions_addclose (actions, max_fd); + } } static void ]]] The regress passes and while this workaround may be temporarly acceptable I -personally- don't like it much. There's a reason guile can't set CLOEXEC for all the file descriptors > 2 obtained via open, socket, pipe, ... like perl -for example- does?