From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 14/14] lei: pass FD to CWD via cmsg, use fchdir on server
Date: Wed, 13 Jan 2021 19:06:27 -1200 [thread overview]
Message-ID: <20210114070627.18195-15-e@80x24.org> (raw)
In-Reply-To: <20210114070627.18195-1-e@80x24.org>
Perl chdir() automatically does fchdir(2) if given a file
or directory handle since 5.8.8/5.10.0, so we can safely
rely on it given our 5.10.1+ requirement.
This means we no longer have to waste several milliseconds
loading the Cwd.so and making stat() calls to ensure
ENV{PWD} is correct and usable in the server. It also lets
us work in directories that are no longer accessible via
pathname.
---
lib/PublicInbox/LEI.pm | 14 +++++++-------
script/lei | 18 +++---------------
t/lei.t | 27 ++-------------------------
3 files changed, 12 insertions(+), 47 deletions(-)
diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index 9786e7ac..1f4a3082 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -674,9 +674,9 @@ sub accept_dispatch { # Listener {post_accept} callback
select($rvec, undef, undef, 1) or
return send($sock, 'timed out waiting to recv FDs', MSG_EOR);
my @fds = $recv_cmd->($sock, my $buf, 4096 * 33); # >MAX_ARG_STRLEN
- if (scalar(@fds) == 3) {
+ if (scalar(@fds) == 4) {
my $i = 0;
- for my $rdr (qw(<&= >&= >&=)) {
+ for my $rdr (qw(<&= >&= >&= <&=)) {
my $fd = shift(@fds);
open($self->{$i++}, $rdr, $fd) and next;
send($sock, "open($rdr$fd) (FD=$i): $!", MSG_EOR);
@@ -692,13 +692,13 @@ sub accept_dispatch { # Listener {post_accept} callback
my ($argc, @argv) = split(/\0/, $buf, -1);
undef $buf;
my %env = map { split(/=/, $_, 2) } splice(@argv, $argc);
- if (chdir($env{PWD})) {
+ if (chdir(delete($self->{3}))) {
local %ENV = %env;
$self->{env} = \%env;
eval { dispatch($self, @argv) };
send($sock, $@, MSG_EOR) if $@;
} else {
- send($sock, "chdir($env{PWD}): $!", MSG_EOR); # implicit close
+ send($sock, "fchdir: $!", MSG_EOR); # implicit close
}
}
@@ -746,7 +746,7 @@ our $oldset; sub oldset { $oldset }
# lei(1) calls this when it can't connect
sub lazy_start {
- my ($path, $errno, $nfd) = @_;
+ my ($path, $errno, $narg) = @_;
if ($errno == ECONNREFUSED) {
unlink($path) or die "unlink($path): $!";
} elsif ($errno != ENOENT) {
@@ -761,7 +761,7 @@ sub lazy_start {
my $dev_ino_expect = pack('dd', $st[0], $st[1]); # dev+ino
pipe(my ($eof_r, $eof_w)) or die "pipe: $!";
local $oldset = PublicInbox::DS::block_signals();
- if ($nfd == 4) {
+ if ($narg == 5) {
$send_cmd = PublicInbox::Spawn->can('send_cmd4');
$recv_cmd = PublicInbox::Spawn->can('recv_cmd4') // do {
require PublicInbox::CmdIPC4;
@@ -770,7 +770,7 @@ sub lazy_start {
};
}
$recv_cmd or die <<"";
-(Socket::MsgHdr || Inline::C) missing/unconfigured (nfd=$nfd);
+(Socket::MsgHdr || Inline::C) missing/unconfigured (narg=$narg);
require PublicInbox::Listener;
require PublicInbox::EOFpipe;
diff --git a/script/lei b/script/lei
index 9610a876..a4a0217b 100755
--- a/script/lei
+++ b/script/lei
@@ -6,7 +6,7 @@ use v5.10.1;
use Socket qw(AF_UNIX SOCK_SEQPACKET MSG_EOR pack_sockaddr_un);
use Errno qw(EINTR ECONNRESET);
use PublicInbox::CmdIPC4;
-my $narg = 4;
+my $narg = 5;
my ($sock, $pwd);
my $recv_cmd = PublicInbox::CmdIPC4->can('recv_cmd4');
my $send_cmd = PublicInbox::CmdIPC4->can('send_cmd4') // do {
@@ -74,25 +74,13 @@ connect($path): $! (after attempted daemon start)
Falling back to (slow) one-shot mode
}
- require Cwd;
- $pwd = $ENV{PWD} // '';
- my $cwd = Cwd::fastcwd() // die "fastcwd(PWD=$pwd): $!";
- if ($pwd ne $cwd) { # prefer ENV{PWD} if it's a symlink to real cwd
- my @st_cwd = stat($cwd) or die "stat(cwd=$cwd): $!";
- my @st_pwd = stat($pwd); # PWD invalid, use cwd
- # make sure st_dev/st_ino match for {PWD} to be valid
- $pwd = $cwd if (!@st_pwd || $st_pwd[1] != $st_cwd[1] ||
- $st_pwd[0] != $st_cwd[0]);
- } else {
- $pwd = $cwd;
- }
1;
}) { # (Socket::MsgHdr|Inline::C), $sock, $pwd are all available:
- $ENV{PWD} = $pwd;
+ open my $dh, '<', '.' or die "open(.) $!";
my $buf = join("\0", scalar(@ARGV), @ARGV);
while (my ($k, $v) = each %ENV) { $buf .= "\0$k=$v" }
$buf .= "\0\0";
- $send_cmd->($sock, [ 0, 1, 2 ], $buf, MSG_EOR);
+ $send_cmd->($sock, [ 0, 1, 2, fileno($dh) ], $buf, MSG_EOR);
$SIG{TERM} = $SIG{INT} = $SIG{QUIT} = sub {
my ($sig) = @_; # 'TERM', not an integer :<
$SIG{$sig} = 'DEFAULT';
diff --git a/t/lei.t b/t/lei.t
index 240735bf..2349dca4 100644
--- a/t/lei.t
+++ b/t/lei.t
@@ -208,9 +208,9 @@ if ($ENV{TEST_LEI_ONESHOT}) {
SKIP: { # real socket
require_mods(qw(Cwd), my $nr = 105);
- my $nfd = eval { require Socket::MsgHdr; 4 } // do {
+ my $nfd = eval { require Socket::MsgHdr; 5 } // do {
require PublicInbox::Spawn;
- PublicInbox::Spawn->can('send_cmd4') ? 4 : undef;
+ PublicInbox::Spawn->can('send_cmd4') ? 5 : undef;
} //
skip 'Socket::MsgHdr or Inline::C missing or unconfigured', $nr;
@@ -260,29 +260,6 @@ SKIP: { # real socket
like($out, qr/^usage: /, 'help output works');
chmod 0700, $sock or BAIL_OUT "chmod 0700: $!";
}
- if ('oneshot on cwd gone') {
- my $cwd = Cwd::fastcwd() or BAIL_OUT "fastcwd: $!";
- my $d = "$home/to-be-removed";
- my $lei_path = 'lei';
- # we chdir, so we need an abs_path fur run_script
- if (($ENV{TEST_RUN_MODE}//2) != 2) {
- $lei_path = PublicInbox::TestCommon::key2script('lei');
- $lei_path = Cwd::abs_path($lei_path);
- }
- mkdir $d or BAIL_OUT "mkdir($d) $!";
- chdir $d or BAIL_OUT "chdir($d) $!";
- if (rmdir($d)) {
- $out = $err = '';
- ok(run_script([$lei_path, 'help'], undef, $opt),
- 'cwd fail, one-shot fallback works');
- } else {
- $err = "rmdir=$!";
- }
- chdir $cwd or BAIL_OUT "chdir($cwd) $!";
- like($err, qr/cwd\(/, 'cwd error noted');
- like($out, qr/^usage: /, 'help output still works');
- }
-
unlink $sock or BAIL_OUT "unlink($sock) $!";
for (0..100) {
kill('CHLD', $new_pid) or last;
prev parent reply other threads:[~2021-01-14 7:06 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-14 7:06 [PATCH 00/14] lei: another pile of changes Eric Wong
2021-01-14 7:06 ` [PATCH 01/14] cmd_ipc: support + test EINTR + EAGAIN, no FDs Eric Wong
2021-01-14 7:06 ` [PATCH 02/14] lei: test SIGPIPE, stop xsearch workers on client abort Eric Wong
2021-01-14 7:06 ` [PATCH 03/14] daemon+watch: fix localization of %SIG for non-signalfd users Eric Wong
2021-01-14 7:06 ` [PATCH 04/14] lei: do not unlink socket path at exit Eric Wong
2021-01-14 7:06 ` [PATCH 05/14] lei: reduce live FD references in wq child Eric Wong
2021-01-14 7:06 ` [PATCH 06/14] lei: rely on localized $current_lei for warnings Eric Wong
2021-01-14 7:06 ` [PATCH 07/14] lei_dedupe+shared_kv: ensure round-tripping serialization Eric Wong
2021-01-14 7:06 ` [PATCH 08/14] lei q: reinstate smsg dedupe Eric Wong
2021-01-14 7:06 ` [PATCH 09/14] search: rename "ts:" prefix to "rt:" Eric Wong
2021-01-14 7:06 ` [PATCH 10/14] lei_overview: rename "references" to "refs" Eric Wong
2021-01-14 7:06 ` [PATCH 11/14] lei: q: lock stdout on overview output Eric Wong
2021-01-15 0:18 ` Eric Wong
2021-01-14 7:06 ` [PATCH 12/14] leixsearch: remove some commented out code Eric Wong
2021-01-14 7:06 ` [PATCH 13/14] lei: remove temporary var on open Eric Wong
2021-01-14 7:06 ` Eric Wong [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://public-inbox.org/README
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210114070627.18195-15-e@80x24.org \
--to=e@80x24.org \
--cc=meta@public-inbox.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/public-inbox.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).