From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.2 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 7496B1F87C for ; Tue, 17 Oct 2023 23:38:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=80x24.org; s=selector1; t=1697585898; bh=JDTm5GuiYq7yB6TvZa6k5+83p8MN/2NMWOjD7iNQP68=; h=From:To:Subject:Date:In-Reply-To:References:From; b=g2O+TSB4Pv9nv39q3oTtBJ4Mv2JrPSWL1zP7u1RjC3b7Z7Mr+m1JAhMKoLt5AfeNa Xz7+7XNO8fXlg4m/pJs2SoG6i9QniYIHxT5/9deC4kjjD6TSdq5ar0+z3tKKapkFiR /Ob5m4F0P7r2yliLJXJ9Rn3kcSrfQtUi8f9YdBkA= From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 14/30] ds: introduce and use do_fork helper Date: Tue, 17 Oct 2023 23:37:59 +0000 Message-ID: <20231017233815.1637932-15-e@80x24.org> In-Reply-To: <20231017233815.1637932-1-e@80x24.org> References: <20231017233815.1637932-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: This ensures we handle RNG reseeding and resetting the event loop properly in child processes after forking. --- lib/PublicInbox/DS.pm | 12 ++++++++++++ lib/PublicInbox/Daemon.pm | 16 +++++----------- lib/PublicInbox/IPC.pm | 12 ++---------- lib/PublicInbox/TestCommon.pm | 3 +-- lib/PublicInbox/Watch.pm | 11 ++--------- lib/PublicInbox/Xapcmd.pm | 5 ++--- 6 files changed, 24 insertions(+), 35 deletions(-) diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm index eefbdcc3..9960937d 100644 --- a/lib/PublicInbox/DS.pm +++ b/lib/PublicInbox/DS.pm @@ -34,6 +34,7 @@ use PublicInbox::Tmpfile; 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 @@ -737,6 +738,17 @@ sub awaitpid { } } +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; diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index 520cef72..f33f6f17 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -541,17 +541,11 @@ sub reap_worker { # awaitpid CB 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(); @@ -563,9 +557,9 @@ sub start_worker ($) { } 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 { diff --git a/lib/PublicInbox/IPC.pm b/lib/PublicInbox/IPC.pm index 5964645e..3292d960 100644 --- a/lib/PublicInbox/IPC.pm +++ b/lib/PublicInbox/IPC.pm @@ -102,12 +102,8 @@ sub ipc_worker_spawn { 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); @@ -341,13 +337,9 @@ sub _wq_worker_start { 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}) // {}}; diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 323152b4..77da822b 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -549,9 +549,8 @@ sub start_script { 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 $!"; } diff --git a/lib/PublicInbox/Watch.pm b/lib/PublicInbox/Watch.pm index 3426d4a7..41b77dc1 100644 --- a/lib/PublicInbox/Watch.pm +++ b/lib/PublicInbox/Watch.pm @@ -385,7 +385,6 @@ sub watch_atfork_child ($) { 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 @@ -413,11 +412,8 @@ sub imap_idle_reap { # awaitpid callback 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); @@ -477,11 +473,8 @@ sub poll_fetch_fork { # DS::add_timer callback 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; diff --git a/lib/PublicInbox/Xapcmd.pm b/lib/PublicInbox/Xapcmd.pm index 4e055acf..c2b66e69 100644 --- a/lib/PublicInbox/Xapcmd.pm +++ b/lib/PublicInbox/Xapcmd.pm @@ -11,6 +11,7 @@ use PublicInbox::SearchIdx; 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") @@ -102,10 +103,8 @@ sub commit_changes ($$$$) { 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);