]> Sergey Matveev's repositories - public-inbox.git/commitdiff
tmpfile: give temporary files meaningful names
authorEric Wong <e@80x24.org>
Thu, 12 Sep 2019 08:34:20 +0000 (08:34 +0000)
committerEric Wong <e@80x24.org>
Sat, 14 Sep 2019 09:24:23 +0000 (09:24 +0000)
Although we always unlink temporary files, give them a
meaningful name so that we can we can still make sense
of the pre-unlink name when using lsof(8) or similar
tools on Linux.

MANIFEST
lib/PublicInbox/Git.pm
lib/PublicInbox/GitHTTPBackend.pm
lib/PublicInbox/HTTP.pm
lib/PublicInbox/SolverGit.pm
lib/PublicInbox/Tmpfile.pm [new file with mode: 0644]
lib/PublicInbox/ViewVCS.pm

index 242803512eb728f276de7d40408fc80b8254f0b6..777367d045406550b6d642237531eb39d596c7d3 100644 (file)
--- a/MANIFEST
+++ b/MANIFEST
@@ -135,6 +135,7 @@ lib/PublicInbox/Spawn.pm
 lib/PublicInbox/SpawnPP.pm
 lib/PublicInbox/Syscall.pm
 lib/PublicInbox/TLS.pm
+lib/PublicInbox/Tmpfile.pm
 lib/PublicInbox/Unsubscribe.pm
 lib/PublicInbox/UserContent.pm
 lib/PublicInbox/V2Writable.pm
index d048051ea1e48479d0585ae2df04fa0a67aaa681..ff3838b3ff8b7fc5d9baeda7c3cb5bb03a4d79b8 100644 (file)
@@ -12,6 +12,7 @@ use warnings;
 use POSIX qw(dup2);
 require IO::Handle;
 use PublicInbox::Spawn qw(spawn popen_rd);
+use PublicInbox::Tmpfile;
 use base qw(Exporter);
 our @EXPORT_OK = qw(git_unquote git_quote);
 
@@ -110,7 +111,8 @@ sub _bidi_pipe {
                        qw(-c core.abbrev=40 cat-file), $batch);
        my $redir = { 0 => fileno($out_r), 1 => fileno($in_w) };
        if ($err) {
-               open(my $fh, '+>', undef) or fail($self, "open.err failed: $!");
+               my $id = "git.$self->{git_dir}$batch.err";
+               my $fh = tmpfile($id) or fail($self, "tmpfile($id): $!");
                $self->{$err} = $fh;
                $redir->{2} = fileno($fh);
        }
index c8878145b8c35488aa2ad32748bc5049dbda7c3b..a8337035f207b75ffec2e3fe024def52d1399d1b 100644 (file)
@@ -12,6 +12,7 @@ use HTTP::Date qw(time2str);
 use HTTP::Status qw(status_message);
 use Plack::Util;
 use PublicInbox::Qspawn;
+use PublicInbox::Tmpfile;
 
 # 32 is same as the git-daemon connection limit
 my $default_limiter = PublicInbox::Qspawn::Limiter->new(32);
@@ -218,7 +219,8 @@ sub input_prepare {
        if (defined $fd && $fd >= 0) {
                return { 0 => $fd };
        }
-       open(my $in, '+>', undef);
+       my $id = "git-http.input.$env->{REMOTE_HOST}:$env->{REMOTE_PORT}";
+       my $in = tmpfile($id);
        unless (defined $in) {
                err($env, "could not open temporary file: $!");
                return;
index 19b57d59518d87ec79e0b564bf63a81ed5935c71..b43ef8701c615ac3e86e9b56d8e960ba952e5d80 100644 (file)
@@ -21,6 +21,7 @@ use IO::Handle;
 require PublicInbox::EvCleanup;
 use PublicInbox::DS qw(msg_more);
 use PublicInbox::Syscall qw(EPOLLIN EPOLLONESHOT);
+use PublicInbox::Tmpfile;
 use constant {
        CHUNK_START => -1,   # [a-f0-9]+\r\n
        CHUNK_END => -2,     # \r\n
@@ -325,8 +326,9 @@ sub response_write {
 }
 
 sub input_tmpfile ($) {
-       open($_[0], '+>', undef);
-       $_[0]->autoflush(1);
+       my $input = tmpfile('http.input', $_[0]->{sock}) or return;
+       $input->autoflush(1);
+       $input;
 }
 
 sub input_prepare {
@@ -338,10 +340,10 @@ sub input_prepare {
                        quit($self, 413);
                        return;
                }
-               input_tmpfile($input);
+               $input = input_tmpfile($self);
        } elsif (env_chunked($env)) {
                $len = CHUNK_START;
-               input_tmpfile($input);
+               $input = input_tmpfile($self);
        } else {
                $input = $null_io;
        }
index 49f948958cd45a0bdcf1a9de20114f2cad7b5bd1..8878961e93506c0783fb7aad0fcf656f3850b664 100644 (file)
@@ -15,6 +15,7 @@ use Fcntl qw(SEEK_SET);
 use PublicInbox::Git qw(git_unquote git_quote);
 use PublicInbox::MsgIter qw(msg_iter msg_part_text);
 use PublicInbox::Qspawn;
+use PublicInbox::Tmpfile;
 use URI::Escape qw(uri_escape_utf8);
 
 # POSIX requires _POSIX_ARG_MAX >= 4096, and xargs is required to
@@ -235,7 +236,7 @@ sub prepare_index ($) {
        my $path_a = $di->{path_a} or die "BUG: path_a missing for $oid_full";
        my $mode_a = $di->{mode_a} || extract_old_mode($di);
 
-       open my $in, '+>', undef or die "open: $!";
+       my $in = tmpfile("update-index.$oid_full") or die "tmpfile: $!";
        print $in "$mode_a $oid_full\t$path_a\0" or die "print: $!";
        $in->flush or die "flush: $!";
        sysseek($in, 0, 0) or die "seek: $!";
diff --git a/lib/PublicInbox/Tmpfile.pm b/lib/PublicInbox/Tmpfile.pm
new file mode 100644 (file)
index 0000000..7fda100
--- /dev/null
@@ -0,0 +1,38 @@
+# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+package PublicInbox::Tmpfile;
+use strict;
+use warnings;
+use base qw(Exporter);
+our @EXPORT = qw(tmpfile);
+use Fcntl qw(:DEFAULT);
+use Errno qw(EEXIST);
+require File::Spec;
+
+# use tmpfile instead of open(..., '+>', undef) so we can get an
+# unlinked filename which makes sense when viewed with lsof
+# (at least on Linux)
+# TODO: O_APPEND support (this is the reason I'm not using File::Temp)
+# And if we ever stop caring to have debuggable filenames, O_TMPFILE :)
+sub tmpfile ($;$) {
+       my ($id, $sock) = @_;
+       if (defined $sock) {
+               # add the socket inode number so we can figure out which
+               # socket it belongs to
+               my @st = stat($sock);
+               $id .= '-ino:'.$st[1];
+       }
+       $id =~ tr!/!^!;
+
+       my $fl = O_RDWR | O_CREAT | O_EXCL;
+       do {
+               my $fn = File::Spec->tmpdir . "/$id-".time.'-'.rand;
+               if (sysopen(my $fh, $fn, $fl, 0600)) { # likely
+                       unlink($fn) or die "unlink($fn): $!"; # FS broken
+                       return $fh; # success
+               }
+       } while ($! == EEXIST);
+       undef  # EMFILE/ENFILE/ENOSPC/ENOMEM
+}
+
+1;
index 60a62e577ab731050dfbcabcdae6c17cda093bb0..369afe93bd2a528a9155a2f7ce0a2d43097dd5fb 100644 (file)
@@ -20,6 +20,7 @@ use bytes (); # only for bytes::length
 use PublicInbox::SolverGit;
 use PublicInbox::WwwStream;
 use PublicInbox::Linkify;
+use PublicInbox::Tmpfile;
 use PublicInbox::Hval qw(ascii_html to_filename);
 my $hl = eval {
        require PublicInbox::HlMod;
@@ -185,7 +186,7 @@ sub show ($$;$) {
                $hints->{$to} = $v;
        }
 
-       open my $log, '+>', undef or die "open: $!";
+       my $log = tmpfile("solve.$oid_b");
        my $solver = PublicInbox::SolverGit->new($ctx->{-inbox}, sub {
                solve_result($ctx, $_[0], $log, $hints, $fn);
        });