diff --git a/core/org.eclipse.cdt.core.linux.aarch64/os/linux/aarch64/libspawner.so b/core/org.eclipse.cdt.core.linux.aarch64/os/linux/aarch64/libspawner.so index af56945007e..8eaf3f18eae 100755 Binary files a/core/org.eclipse.cdt.core.linux.aarch64/os/linux/aarch64/libspawner.so and b/core/org.eclipse.cdt.core.linux.aarch64/os/linux/aarch64/libspawner.so differ diff --git a/core/org.eclipse.cdt.core.linux.ppc64le/os/linux/ppc64le/libspawner.so b/core/org.eclipse.cdt.core.linux.ppc64le/os/linux/ppc64le/libspawner.so index 5ddb32a2cdb..b472ea7639e 100755 Binary files a/core/org.eclipse.cdt.core.linux.ppc64le/os/linux/ppc64le/libspawner.so and b/core/org.eclipse.cdt.core.linux.ppc64le/os/linux/ppc64le/libspawner.so differ diff --git a/core/org.eclipse.cdt.core.linux.x86_64/os/linux/x86_64/libspawner.so b/core/org.eclipse.cdt.core.linux.x86_64/os/linux/x86_64/libspawner.so index 0e0ad421cdb..198c2952f93 100755 Binary files a/core/org.eclipse.cdt.core.linux.x86_64/os/linux/x86_64/libspawner.so and b/core/org.eclipse.cdt.core.linux.x86_64/os/linux/x86_64/libspawner.so differ diff --git a/core/org.eclipse.cdt.core.macosx/os/macosx/aarch64/libspawner.jnilib b/core/org.eclipse.cdt.core.macosx/os/macosx/aarch64/libspawner.jnilib index f983fc2f87f..34c41c3623f 100755 Binary files a/core/org.eclipse.cdt.core.macosx/os/macosx/aarch64/libspawner.jnilib and b/core/org.eclipse.cdt.core.macosx/os/macosx/aarch64/libspawner.jnilib differ diff --git a/core/org.eclipse.cdt.core.macosx/os/macosx/x86_64/libspawner.jnilib b/core/org.eclipse.cdt.core.macosx/os/macosx/x86_64/libspawner.jnilib index f3bc76b6977..5f3406c40e9 100755 Binary files a/core/org.eclipse.cdt.core.macosx/os/macosx/x86_64/libspawner.jnilib and b/core/org.eclipse.cdt.core.macosx/os/macosx/x86_64/libspawner.jnilib differ diff --git a/core/org.eclipse.cdt.core.native/native_src/unix/exec_unix.c b/core/org.eclipse.cdt.core.native/native_src/unix/exec_unix.c index e393cfff6a0..8afc663cdeb 100644 --- a/core/org.eclipse.cdt.core.native/native_src/unix/exec_unix.c +++ b/core/org.eclipse.cdt.core.native/native_src/unix/exec_unix.c @@ -21,10 +21,76 @@ #include #include #include +#include +#include +#include /* from pfind.c */ extern char *pfind(const char *name, char *const envp[]); +static int sys_close_range_wrapper(unsigned int from_fd_inclusive) { + // Use fast `close_range` (https://man7.org/linux/man-pages/man2/close_range.2.html) if available. + // Cannot call `close_range` from libc, as it may be unavailable in older libc. +#if defined(__linux__) && defined(SYS_close_range) && defined(CLOSE_RANGE_UNSHARE) + return syscall(SYS_close_range, from_fd_inclusive, ~0U, CLOSE_RANGE_UNSHARE); +#else + errno = ENOSYS; + return -1; +#endif +} + +static int close_all_fds_using_parsing(unsigned int from_fd_inclusive) { + // If `opendir` is implemented using a file descriptor, we may close it accidentally. + // Let's close a few lowest file descriptors, in hope that `opendir` will use it. + int lowest_fds_to_close = 2; + for (int i = 0; i < lowest_fds_to_close; i++) { + close(from_fd_inclusive + i); + } + +#if defined(__APPLE__) +#define FD_DIR "/dev/fd" +#else +#define FD_DIR "/proc/self/fd" +#endif + + DIR *dirp = opendir(FD_DIR); + if (dirp == NULL) + return -1; + + struct dirent *direntp; + + while ((direntp = readdir(dirp)) != NULL) { + if (isdigit(direntp->d_name[0])) { + int fd = strtol(direntp->d_name, NULL, 10); + if (fd >= from_fd_inclusive + lowest_fds_to_close && fd != dirfd(dirp)) { + close(fd); + } + } + } + + closedir(dirp); + + return 0; +} + +static void close_all_fds_fallback(unsigned int from_fd_inclusive) { + int fdlimit = sysconf(_SC_OPEN_MAX); + if (fdlimit == -1) + fdlimit = 65535; // arbitrary default, just in case + for (int fd = from_fd_inclusive; fd < fdlimit; fd++) { + close(fd); + } +} + +static void close_all_fds() { + unsigned int from_fd = STDERR_FILENO + 1; + if (sys_close_range_wrapper(from_fd) == 0) + return; + if (close_all_fds_using_parsing(from_fd) == 0) + return; + close_all_fds_fallback(from_fd); +} + pid_t exec0(const char *path, char *const argv[], char *const envp[], const char *dirpath, int channels[3]) { int pipe0[2], pipe1[2], pipe2[2]; pid_t childpid; @@ -83,14 +149,7 @@ pid_t exec0(const char *path, char *const argv[], char *const envp[], const char } /* Close all the fd's in the child */ - { - int fdlimit = sysconf(_SC_OPEN_MAX); - int fd = 3; - - while (fd < fdlimit) { - close(fd++); - } - } + close_all_fds(); setpgid(getpid(), getpid());