From df00ede142da26f0b88c161694bb7508410b9de8 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 24 Dec 2022 10:40:47 +0000 Subject: [PATCH] test_common: avoid needless fcntl in start_script POSIX::dup2 does not do anything in addition to dup2(2) and is thus immune to Perl automatically setting FD_CLOEXEC on FDs it makes into IO objects/globs. We only need to account for the case when both args for dup2 are identical, in which case the kernel treats it as a no-op and then thus we need to clear FD_CLOEXEC ourselves. --- lib/PublicInbox/TestCommon.pm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 888c1f1e..b36c71a6 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -6,7 +6,7 @@ package PublicInbox::TestCommon; use strict; use parent qw(Exporter); use v5.10.1; -use Fcntl qw(FD_CLOEXEC F_SETFD F_GETFD :seek); +use Fcntl qw(F_SETFD :seek); use POSIX qw(dup2); use IO::Socket::INET; use File::Spec; @@ -479,16 +479,14 @@ sub start_script { # pretend to be systemd (cf. sd_listen_fds(3)) # 3 == SD_LISTEN_FDS_START my $fd; - for ($fd = 0; 1; $fd++) { - my $s = $opt->{$fd}; - last if $fd >= 3 && !defined($s); - next unless $s; - my $fl = fcntl($s, F_GETFD, 0); - if (($fl & FD_CLOEXEC) != FD_CLOEXEC) { - warn "got FD:".fileno($s)." w/o CLOEXEC\n"; + for ($fd = 0; $fd < 3 || defined($opt->{$fd}); $fd++) { + my $io = $opt->{$fd} // next; + my $old = fileno($io); + if ($old == $fd) { + fcntl($io, F_SETFD, 0) // die "F_SETFD: $!"; + } else { + dup2($old, $fd) // die "dup2($old, $fd): $!"; } - fcntl($s, F_SETFD, $fl &= ~FD_CLOEXEC); - dup2(fileno($s), $fd) or die "dup2 failed: $!\n"; } %ENV = (%ENV, %$env) if $env; my $fds = $fd - 3; -- 2.44.0