From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-3.9 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 5C6711FB09 for ; Sun, 10 Jan 2021 12:15:20 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 11/22] ipc: DESTROY and wq_workers methods Date: Sun, 10 Jan 2021 12:15:08 +0000 Message-Id: <20210110121519.17044-12-e@80x24.org> In-Reply-To: <20210110121519.17044-1-e@80x24.org> References: <20210110121519.17044-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: We'll enable automatic cleanup when IPC classes go out-of-scope to avoid leaving zombies around. ->wq_workers will be a useful convenience method to change worker counts. --- lib/PublicInbox/IPC.pm | 23 +++++++++++++++++++++-- t/ipc.t | 10 +++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/lib/PublicInbox/IPC.pm b/lib/PublicInbox/IPC.pm index 4d29532c..8a3120c9 100644 --- a/lib/PublicInbox/IPC.pm +++ b/lib/PublicInbox/IPC.pm @@ -276,7 +276,7 @@ sub _wq_worker_start ($$) { if ($pid == 0) { eval { PublicInbox::DS->Reset }; close(delete $self->{-wq_s1}); - delete $self->{qw(-wq_workers -wq_quit)}; + delete $self->{qw(-wq_workers -wq_quit -wq_ppid)}; my $quit = sub { $self->{-wq_quit} = 1 }; $SIG{$_} = $quit for (qw(TERM INT QUIT)); $SIG{$_} = 'IGNORE' for (qw(TTOU TTIN)); @@ -347,10 +347,24 @@ sub wq_worker_decr_wait { dwaitpid($pid, \&ipc_worker_reap, $self); } +# set or retrieve number of workers +sub wq_workers { + my ($self, $nr) = @_; + my $cur = $self->{-wq_workers} or return; + if (defined $nr) { + while (scalar(keys(%$cur)) > $nr) { + $self->wq_worker_decr; + $self->wq_worker_decr_wait; + } + $self->wq_worker_incr while scalar(keys(%$cur)) < $nr; + } + scalar(keys(%$cur)); +} + sub wq_close { my ($self) = @_; delete @$self{qw(-wq_s1 -wq_s2)} or return; - my $ppid = delete $self->{-wq_ppid} // die 'BUG: no wq_ppid'; + my $ppid = delete $self->{-wq_ppid} or return; my $workers = delete $self->{-wq_workers} // die 'BUG: no wq_workers'; return if $ppid != $$; # can't reap siblings or parents for my $pid (keys %$workers) { @@ -358,4 +372,9 @@ sub wq_close { } } +sub DESTROY { + wq_close($_[0]); + ipc_worker_stop($_[0]); +} + 1; diff --git a/t/ipc.t b/t/ipc.t index 51e347c6..903294c5 100644 --- a/t/ipc.t +++ b/t/ipc.t @@ -170,11 +170,15 @@ is($warn[2], $warn[1], 'worker did not die'); $SIG{__WARN__} = 'DEFAULT'; is($ipc->wq_workers_start('wq', 1), $$, 'workers started again'); -is(scalar(keys %{$ipc->{-wq_workers}}), 1, '1 worker started'); +is($ipc->wq_workers, 1, '1 worker started'); $ipc->wq_worker_incr; -is(scalar(keys %{$ipc->{-wq_workers}}), 2, 'worker count bumped'); +is($ipc->wq_workers, 2, 'worker count bumped'); $ipc->wq_worker_decr; $ipc->wq_worker_decr_wait(10); -is(scalar(keys %{$ipc->{-wq_workers}}), 1, 'worker count lowered'); +is($ipc->wq_workers, 1, 'worker count lowered'); +is($ipc->wq_workers(2), 2, 'worker count set'); +is($ipc->wq_workers, 2, 'worker count stayed set'); +$ipc->wq_close; +is($ipc->wq_workers, undef, 'workers undef after close'); done_testing;