user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
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;

      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).