commit c308da0802b3c24a3aa6dbf944c256fcf03b88f0
parent 9543f477330e07de1b50bc6eb0e3bed97f748246
Author: Egor <egor@opensrc.club>
Date: Tue, 10 May 2022 20:03:56 +0300
os::exec: clear FD_CLOEXEC when dup2ing fd to itself
If you try to dup2 a fd to itself, it's a no-op. Since we want the child
process to inherit the fd, we must ensure to clear CLOEXEC in this case.
posix_spawn_file_actions_adddup2 in musl and glibc works similarly.
Signed-off-by: Egor <egor@opensrc.club>
Diffstat:
3 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/os/exec/exec+freebsd.ha b/os/exec/exec+freebsd.ha
@@ -119,10 +119,20 @@ fn platform_exec(cmd: *command) error = {
continue;
};
- match (rt::dup2(from, cmd.files[i].1)) {
- case int => void;
- case let e: rt::errno =>
- return errors::errno(e);
+ if (cmd.files[i].1 == from) {
+ let flags = match (rt::fcntl(from, rt::F_GETFD, 0)) {
+ case let flags: int =>
+ yield flags;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
+ rt::fcntl(from, rt::F_SETFD, flags & ~rt::FD_CLOEXEC)!;
+ } else {
+ match (rt::dup2(from, cmd.files[i].1)) {
+ case int => void;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
};
};
diff --git a/os/exec/exec+linux.ha b/os/exec/exec+linux.ha
@@ -120,10 +120,20 @@ fn platform_exec(cmd: *command) error = {
continue;
};
- match (rt::dup2(from, cmd.files[i].1)) {
- case int => void;
- case let e: rt::errno =>
- return errors::errno(e);
+ if (cmd.files[i].1 == from) {
+ let flags = match (rt::fcntl(from, rt::F_GETFD, 0)) {
+ case let flags: int =>
+ yield flags;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
+ rt::fcntl(from, rt::F_SETFD, flags & ~rt::FD_CLOEXEC)!;
+ } else {
+ match (rt::dup2(from, cmd.files[i].1)) {
+ case int => void;
+ case let e: rt::errno =>
+ return errors::errno(e);
+ };
};
};
diff --git a/rt/+linux/types.ha b/rt/+linux/types.ha
@@ -242,6 +242,8 @@ export def F_SETOWN_EX: int = 15;
export def F_GETOWN_EX: int = 16;
export def F_GETOWNER_UIDS: int = 17;
+export def FD_CLOEXEC: int = 1;
+
export type st_flock = struct {
l_type: i16,
l_whence: i16,