+sub out ($;@) {
+ my $self = shift;
+ return if print { $self->{1} // return } @_; # likely
+ return note_sigpipe($self, 1) if $! == EPIPE;
+ my $err = "error writing to stdout: $!";
+ delete $self->{1};
+ fail($self, $err);
+}
+
+sub puts ($;@) { out(shift, map { "$_\n" } @_) }
+
+sub child_error { # passes non-fatal curl exit codes to user
+ my ($self, $child_error, $msg) = @_; # child_error is $?
+ $self->err($msg) if $msg;
+ if (my $s = $self->{pkt_op_p} // $self->{sock}) {
+ # send to the parent lei-daemon or to lei(1) client
+ send($s, "child_error $child_error", MSG_EOR);
+ } elsif (!$PublicInbox::DS::in_loop) {
+ $self->{child_error} = $child_error;
+ } # else noop if client disconnected
+}
+
+sub note_sigpipe { # triggers sigpipe_handler
+ my ($self, $fd) = @_;
+ close(delete($self->{$fd})); # explicit close silences Perl warning
+ send($self->{pkt_op_p}, '|', MSG_EOR) if $self->{pkt_op_p};
+ x_it($self, 13);
+}
+
+sub lei_atfork_child {
+ my ($self, $persist) = @_;
+ # we need to explicitly close things which are on stack
+ if ($persist) {
+ my @io = delete @$self{0,1,2};
+ unless ($self->{oneshot}) {
+ close($_) for @io;
+ }
+ } else {
+ delete $self->{0};
+ }
+ for (delete @$self{qw(3 sock old_1 au_done)}) {
+ close($_) if defined($_);
+ }
+ if (my $op_c = delete $self->{pkt_op_c}) {
+ close(delete $op_c->{sock});
+ }
+ if (my $pgr = delete $self->{pgr}) {
+ close($_) for (@$pgr[1,2]);
+ }
+ close $listener if $listener;
+ undef $listener;
+ %PATH2CFG = ();
+ undef $errors_log;
+ $quit = \&CORE::exit;
+ $current_lei = $persist ? undef : $self; # for SIG{__WARN__}
+}
+