[libc-commits] [libc] 3c7727f - [libc] Use the dup2 syscall wrapper in posix_spawn (#207879)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 7 07:09:05 PDT 2026


Author: Mikhail R. Gadelha
Date: 2026-07-07T11:09:00-03:00
New Revision: 3c7727f1269e5986915aacf4ee1ae117843bd573

URL: https://github.com/llvm/llvm-project/commit/3c7727f1269e5986915aacf4ee1ae117843bd573
DIFF: https://github.com/llvm/llvm-project/commit/3c7727f1269e5986915aacf4ee1ae117843bd573.diff

LOG: [libc] Use the dup2 syscall wrapper in posix_spawn (#207879)

posix_spawn's local dup2 helper fell back to a bare dup3 on targets
without SYS_dup2. dup3 fails with EINVAL when oldfd == newfd, where dup2
must instead return oldfd if it is valid, so
posix_spawn_file_actions_adddup2 with equal fds misbehaved on those
targets. linux_syscalls::dup2 already implements the correct fallback,
so call it directly and drop the local helper.

Added: 
    

Modified: 
    libc/src/spawn/linux/CMakeLists.txt
    libc/src/spawn/linux/posix_spawn.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/spawn/linux/CMakeLists.txt b/libc/src/spawn/linux/CMakeLists.txt
index 42057e9f12fec..910705af85b3d 100644
--- a/libc/src/spawn/linux/CMakeLists.txt
+++ b/libc/src/spawn/linux/CMakeLists.txt
@@ -11,6 +11,7 @@ add_entrypoint_object(
     libc.include.sys_syscall
     libc.include.signal
     libc.src.__support.OSUtil.osutil
+    libc.src.__support.OSUtil.linux.syscall_wrappers.dup2
     libc.src.__support.OSUtil.linux.syscall_wrappers.open
     libc.src.spawn.file_actions
     libc.src.signal.linux.signal_utils

diff  --git a/libc/src/spawn/linux/posix_spawn.cpp b/libc/src/spawn/linux/posix_spawn.cpp
index 301be6d7c8762..2961dd5c6b82c 100644
--- a/libc/src/spawn/linux/posix_spawn.cpp
+++ b/libc/src/spawn/linux/posix_spawn.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/spawn/posix_spawn.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/dup2.h"
 #include "src/__support/OSUtil/linux/syscall_wrappers/open.h"
 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
 #include "src/__support/common.h"
@@ -41,18 +42,6 @@ pid_t fork() {
 
 void close(int fd) { LIBC_NAMESPACE::syscall_impl<long>(SYS_close, fd); }
 
-// We use dup3 if dup2 is not available, similar to our implementation of dup2
-bool dup2(int fd, int newfd) {
-#ifdef SYS_dup2
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_dup2, fd, newfd);
-#elif defined(SYS_dup3)
-  int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_dup3, fd, newfd, 0);
-#else
-#error "dup2 and dup3 syscalls not available."
-#endif
-  return ret < 0 ? false : true;
-}
-
 // All exits from child_process are error exits. So, we use a simple
 // exit implementation which exits with code 127.
 void exit() {
@@ -84,7 +73,8 @@ void child_process(const char *__restrict path,
           exit();
         int actual_fd = *fd;
         if (actual_fd != open_act->fd) {
-          bool dup2_result = dup2(actual_fd, open_act->fd);
+          bool dup2_result =
+              linux_syscalls::dup2(actual_fd, open_act->fd).has_value();
           close(actual_fd); // The old fd is not needed anymore.
           if (!dup2_result)
             exit();
@@ -98,7 +88,7 @@ void child_process(const char *__restrict path,
       }
       case BaseSpawnFileAction::DUP2: {
         auto *dup2_act = reinterpret_cast<SpawnFileDup2Action *>(act);
-        if (!dup2(dup2_act->fd, dup2_act->newfd))
+        if (!linux_syscalls::dup2(dup2_act->fd, dup2_act->newfd).has_value())
           exit();
         break;
       }


        


More information about the libc-commits mailing list