]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/DS.pm
ds: cleanup poll test and avoid clobbering imports
[public-inbox.git] / lib / PublicInbox / DS.pm
index e3479e666342062b4eade4b4d3371580e0e28127..a8700bc53e8c417e7be1bf725ed51e7337e852ba 100644 (file)
@@ -18,7 +18,7 @@ use strict;
 use bytes;
 use POSIX ();
 use IO::Handle qw();
-use Fcntl qw(FD_CLOEXEC F_SETFD F_GETFD SEEK_SET);
+use Fcntl qw(SEEK_SET :DEFAULT);
 use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
 use parent qw(Exporter);
 our @EXPORT_OK = qw(now msg_more);
@@ -32,9 +32,9 @@ use fields ('sock',              # underlying socket
             'wbuf_off',  # offset into first element of wbuf to start writing at
             );
 
-use Errno  qw(EAGAIN EINVAL);
+use Errno  qw(EAGAIN EINVAL EEXIST);
 use Carp   qw(croak confess carp);
-use File::Temp qw(tempfile);
+require File::Spec;
 
 our (
      %DescriptorMap,             # fd (num) -> PublicInbox::DS object
@@ -151,7 +151,7 @@ sub _InitPoller
             $cls = "PublicInbox::$_";
             last if eval "require $cls";
         }
-        $cls->import;
+        $cls->import(qw(epoll_ctl epoll_wait));
         $Epoll = $cls->new;
     }
     *EventLoop = *EpollEventLoop;
@@ -440,12 +440,16 @@ sub drop {
 # PerlIO::mmap or PerlIO::scalar if needed
 sub tmpio ($$$) {
     my ($self, $bref, $off) = @_;
-    # open(my $fh, '+>>', undef) doesn't set O_APPEND
-    my ($fh, $path) = eval { tempfile('wbuf-XXXXXXX', TMPDIR => 1) };
-    $fh or return drop($self, "tempfile: $@");
-    open($fh, '+>>', $path) or return drop($self, "open: $!");
+    my $fh; # open(my $fh, '+>>', undef) doesn't set O_APPEND
+    do {
+        my $fn = File::Spec->tmpdir . '/wbuf-' . rand;
+        if (sysopen($fh, $fn, O_RDWR|O_CREAT|O_EXCL|O_APPEND, 0600)) { # likely
+            unlink($fn) or return drop($self, "unlink($fn) $!");
+        } elsif ($! != EEXIST) { # EMFILE/ENFILE/ENOSPC/ENOMEM
+            return drop($self, "open: $!");
+        }
+    } until (defined $fh);
     $fh->autoflush(1);
-    unlink($path) or return drop($self, "unlink: $!");
     my $len = bytes::length($$bref) - $off;
     $fh->write($$bref, $len, $off) or return drop($self, "write ($len): $!");
     $fh
@@ -501,7 +505,10 @@ sub write {
             return $self->close;
         }
         my $tmpio = tmpio($self, $bref, $written) or return 0;
-        $self->{wbuf} = [ $tmpio ];
+
+        # wbuf may be an empty array if we're being called inside
+        # ->flush_write via CODE bref:
+        push @{$self->{wbuf} ||= []}, $tmpio;
         watch($self, EPOLLOUT|EPOLLONESHOT);
         return 0;
     }