use PublicInbox::Select;
use Errno qw(EAGAIN EINVAL ECHILD);
use Carp qw(carp croak);
+use autodie qw(fork);
our @EXPORT_OK = qw(now msg_more awaitpid add_timer add_uniq_timer);
my $nextq; # queue for next_tick
}
}
+sub do_fork () {
+ my $seed = rand(0xffffffff);
+ my $pid = fork;
+ if ($pid == 0) {
+ srand($seed);
+ eval { Net::SSLeay::randomize() };
+ Reset();
+ }
+ $pid;
+}
+
package PublicInbox::DummyPoller; # only used during Reset
use v5.12;
sub start_worker ($) {
my ($nr) = @_;
- my $seed = rand(0xffffffff);
return unless @listeners;
- my $pid = fork;
- if (!defined($pid)) {
- warn "fork: $!";
- } elsif ($pid == 0) {
+ my $pid = PublicInbox::DS::do_fork;
+ if ($pid == 0) {
undef %WORKERS;
- PublicInbox::DS::Reset();
local $PublicInbox::DS::Poller; # allow epoll/kqueue
- srand($seed);
- eval { Net::SSLeay::randomize() };
$set_user->() if $set_user;
PublicInbox::EOFpipe->new($parent_pipe, \&worker_quit);
worker_loop();
}
sub start_workers {
- for my $nr (grep { !defined($WORKERS{$_}) } (0..($nworker - 1))) {
- start_worker($nr);
- }
+ my @idx = grep { !defined($WORKERS{$_}) } (0..($nworker - 1)) or return;
+ eval { start_worker($_) for @idx };
+ warn "E: $@\n" if $@;
}
sub trim_workers {
pipe(my $r_res, my $w_res);
my $sigset = $oldset // PublicInbox::DS::block_signals();
$self->ipc_atfork_prepare;
- my $seed = rand(0xffffffff);
- my $pid = fork;
+ my $pid = PublicInbox::DS::do_fork;
if ($pid == 0) {
- srand($seed);
- eval { Net::SSLeay::randomize() };
- eval { PublicInbox::DS->Reset };
delete @$self{qw(-wq_s1 -wq_s2 -wq_workers -wq_ppid)};
$w_req = $r_res = undef;
$w_res->autoflush(1);
my ($self, $oldset, $fields, $one, @cb_args) = @_;
my ($bcast1, $bcast2);
$one or socketpair($bcast1, $bcast2, AF_UNIX, SOCK_SEQPACKET, 0);
- my $seed = rand(0xffffffff);
- my $pid = fork;
+ my $pid = PublicInbox::DS::do_fork;
if ($pid == 0) {
- srand($seed);
- eval { Net::SSLeay::randomize() };
undef $bcast1;
- eval { PublicInbox::DS->Reset };
delete @$self{qw(-wq_s1 -wq_ppid)};
$self->{-wq_worker_nr} =
keys %{delete($self->{-wq_workers}) // {}};
require PublicInbox::OnDestroy;
my $tmp_mask = PublicInbox::OnDestroy->new(
\&PublicInbox::DS::sig_setmask, $oset);
- my $pid = fork // die "fork: $!";
+ my $pid = PublicInbox::DS::do_fork();
if ($pid == 0) {
- eval { PublicInbox::DS->Reset };
for (@{delete($opt->{-CLOFORK}) // []}) {
close($_) or die "close $!";
}
my ($self) = @_;
delete $self->{pids};
delete $self->{opendirs};
- PublicInbox::DS->Reset;
my $sig = delete $self->{sig};
$sig->{CHLD} = $sig->{HUP} = $sig->{USR1} = 'DEFAULT';
# TERM/QUIT/INT call ->quit, which works in both parent+child
sub imap_idle_fork {
my ($self, $uri, $intvl) = @_;
return if $self->{quit};
- my $seed = rand(0xffffffff);
- my $pid = fork // die "fork: $!";
+ my $pid = PublicInbox::DS::do_fork;
if ($pid == 0) {
- srand($seed);
- eval { Net::SSLeay::randomize() };
watch_atfork_child($self);
watch_imap_idle_1($self, $uri, $intvl);
_exit(0);
my @imap = grep { # push() always returns > 0
$_->scheme =~ m!\Aimaps?!i ? 1 : (push(@nntp, $_) < 0)
} @$uris;
- my $seed = rand(0xffffffff);
- my $pid = fork // die "fork: $!";
+ my $pid = PublicInbox::DS::do_fork;
if ($pid == 0) {
- srand($seed);
- eval { Net::SSLeay::randomize() };
watch_atfork_child($self);
watch_imap_fetch_all($self, \@imap) if @imap;
watch_nntp_fetch_all($self, \@nntp) if @nntp;
use File::Temp 0.19 (); # ->newdir
use File::Path qw(remove_tree);
use POSIX qw(WNOHANG _exit);
+use PublicInbox::DS;
# support testing with dev versions of Xapian which installs
# commands with a version number suffix (e.g. "xapian-compact-1.5")
sub cb_spawn {
my ($cb, $args, $opt) = @_; # $cb = cpdb() or compact()
- my $seed = rand(0xffffffff);
- my $pid = fork // die "fork: $!";
+ my $pid = PublicInbox::DS::do_fork;
return $pid if $pid > 0;
- srand($seed);
$SIG{__DIE__} = sub { warn @_; _exit(1) }; # don't jump up stack
$cb->($args, $opt);
_exit(0);