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-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,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 E9F0B1F8C6; Thu, 29 Jul 2021 10:01:31 +0000 (UTC) Date: Thu, 29 Jul 2021 10:01:31 +0000 From: Eric Wong To: meta@public-inbox.org Subject: [RFC v2] lei: close inotify FD in forked child Message-ID: <20210729100131.GA13673@dcvr> References: <20210728123433.30248-1-e@80x24.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: <20210728123433.30248-1-e@80x24.org> List-Id: It looks like Linux::Inotify2 2.3+ will include an ->fh method to give us the ability to safely close an FD without hitting EBADF (and automatically use FD_CLOEXEC). We'll still need a new wrapper class (LI2Wrap) to handle it for users of old versions, though. http://lists.schmorp.de/pipermail/perl/2021q3/thread.html --- MANIFEST | 1 + lib/PublicInbox/DirIdle.pm | 11 +++++++++++ lib/PublicInbox/LEI.pm | 2 +- lib/PublicInbox/LI2Wrap.pm | 20 ++++++++++++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 lib/PublicInbox/LI2Wrap.pm diff --git a/MANIFEST b/MANIFEST index a3913501..fb9f16bf 100644 --- a/MANIFEST +++ b/MANIFEST @@ -197,6 +197,7 @@ lib/PublicInbox/InputPipe.pm lib/PublicInbox/Isearch.pm lib/PublicInbox/KQNotify.pm lib/PublicInbox/LEI.pm +lib/PublicInbox/LI2Wrap.pm lib/PublicInbox/LeiALE.pm lib/PublicInbox/LeiAddWatch.pm lib/PublicInbox/LeiAuth.pm diff --git a/lib/PublicInbox/DirIdle.pm b/lib/PublicInbox/DirIdle.pm index 65896f95..d572c274 100644 --- a/lib/PublicInbox/DirIdle.pm +++ b/lib/PublicInbox/DirIdle.pm @@ -84,4 +84,15 @@ sub event_step { warn "$self->{inot}->read err: $@\n" if $@; } +sub force_close { + my ($self) = @_; + my $inot = delete $self->{inot} // return; + if ($inot->can('fh')) { # Linux::Inotify2 2.3+ + close($inot->fh) or warn "CLOSE ERROR: $!"; + } elsif ($inot->isa('Linux::Inotify2')) { + require PublicInbox::LI2Wrap; + PublicInbox::LI2Wrap::wrapclose($inot); + } +} + 1; diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm index d9fd40fd..e6f763e1 100644 --- a/lib/PublicInbox/LEI.pm +++ b/lib/PublicInbox/LEI.pm @@ -556,7 +556,7 @@ sub _lei_atfork_child { } close $listener if $listener; undef $listener; - undef $dir_idle; + $dir_idle->force_close if $dir_idle; %PATH2CFG = (); $MDIR2CFGPATH = {}; eval 'no warnings; undef $PublicInbox::LeiNoteEvent::to_flush'; diff --git a/lib/PublicInbox/LI2Wrap.pm b/lib/PublicInbox/LI2Wrap.pm new file mode 100644 index 00000000..b0f4f8b8 --- /dev/null +++ b/lib/PublicInbox/LI2Wrap.pm @@ -0,0 +1,20 @@ +# Copyright (C) all contributors +# License: AGPL-3.0+ + +# Wrapper for Linux::Inotify2 < 2.3 which lacked ->fh and auto-close +# Remove this when supported LTS/enterprise distros are all +# Linux::Inotify2 >= 2.3 +package PublicInbox::LI2Wrap; +use v5.10.1; +our @ISA = qw(Linux::Inotify2); + +sub wrapclose { + my ($inot) = @_; + my $fd = $inot->fileno; + open my $fh, '<&=', $fd or die "open <&= $fd $!"; + +} + +sub DESTROY {} # no-op + +1