]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/ProcessPipe.pm
lei_to_mail: start atomic and compressed mbox writing
[public-inbox.git] / lib / PublicInbox / ProcessPipe.pm
1 # Copyright (C) 2016-2020 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # a tied handle for auto reaping of children tied to a pipe, see perltie(1)
5 package PublicInbox::ProcessPipe;
6 use strict;
7 use v5.10.1;
8
9 sub TIEHANDLE {
10         my ($class, $pid, $fh, $cb, $arg) = @_;
11         bless { pid => $pid, fh => $fh, cb => $cb, arg => $arg }, $class;
12 }
13
14 sub READ { read($_[0]->{fh}, $_[1], $_[2], $_[3] || 0) }
15
16 sub READLINE { readline($_[0]->{fh}) }
17
18 sub WRITE {
19         use bytes qw(length);
20         syswrite($_[0]->{fh}, $_[1], $_[2] // length($_[1]), $_[3] // 0);
21 }
22
23 sub PRINT {
24         my $self = shift;
25         print { $self->{fh} } @_;
26 }
27
28 sub CLOSE {
29         my $fh = delete($_[0]->{fh});
30         my $ret = defined $fh ? close($fh) : '';
31         my ($pid, $cb, $arg) = delete @{$_[0]}{qw(pid cb arg)};
32         if (defined $pid) {
33                 # PublicInbox::DS may not be loaded
34                 eval { PublicInbox::DS::dwaitpid($pid, $cb, $arg) };
35
36                 if ($@) { # ok, not in the event loop, work synchronously
37                         waitpid($pid, 0);
38                         $ret = '' if $?;
39                         $cb->($arg, $pid) if $cb;
40                 }
41         }
42         $ret;
43 }
44
45 sub FILENO { fileno($_[0]->{fh}) }
46
47 sub DESTROY {
48         CLOSE(@_);
49         undef;
50 }
51
52 sub pid { $_[0]->{pid} }
53
54 1;