From 0795b0906cc81f400e0e5b9b53f812627dbd19c0 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 31 Jan 2021 22:28:30 -1000 Subject: 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 --- lib/PublicInbox/DS.pm | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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(); -- cgit v1.2.3-24-ge0c7