From: Eric Wong Date: Mon, 1 Feb 2021 08:28:30 +0000 (-1000) Subject: ds: guard against stack-not-refcounted quirk of Perl 5 X-Git-Tag: v1.7.0~1251 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=0795b0906cc81f400e0e5b9b53f812627dbd19c0;p=public-inbox.git ds: guard against stack-not-refcounted quirk of Perl 5 The Perl 5 stack is weakly-referenced for performance reasons. This means it's possible for items in the stack to be freed while executing further down the stack. In lei (and perhaps public-facing read-only daemons in the future), we'll fork and call PublicInbox::DS->Reset in the child process. This causes %DescriptorMap to be clobbered, allowing the $DescriptorMap{$fd} arg to be freed inside the child process. When Carp::confess or Carp::longmess is called to generate a backtrace, it may access the @DB::args array. This array access is not protected by reference counting and is known to cause segfaults and other weird errors. While the caller of an unnecessary Carp::confess may be eliminated in a future commit, we can't guarantee our dependencies will be free of @DB::args access attempts in the future. So guard against this Perl 5 quirmk by defensively bumping the refcount of any object we call ->event_step on. cf. https://rt.perl.org/Public/Bug/Display.html?id=131046 https://github.com/Perl/perl5/issues/15928 --- diff --git a/lib/PublicInbox/DS.pm b/lib/PublicInbox/DS.pm index 40994fd4..2d312f0a 100644 --- a/lib/PublicInbox/DS.pm +++ b/lib/PublicInbox/DS.pm @@ -271,6 +271,7 @@ sub EventLoop { $Epoll //= _InitPoller(); local $in_loop = 1; my @events; + my $obj; # guard stack-not-refcounted w/ Carp + @DB::args do { my $timeout = RunTimers(); @@ -281,7 +282,8 @@ sub EventLoop { # that ones in the front triggered unregister-interest actions. if we # can't find the %sock entry, it's because we're no longer interested # in that event. - $DescriptorMap{$fd}->event_step; + $obj = $DescriptorMap{$fd}; + $obj->event_step; } } while (PostEventLoop()); _run_later();