diff options
author | Eric Wong <e@80x24.org> | 2021-01-31 22:28:30 -1000 |
---|---|---|
committer | Eric Wong <e@80x24.org> | 2021-02-01 11:38:24 +0000 |
commit | 0795b0906cc81f400e0e5b9b53f812627dbd19c0 (patch) | |
tree | f302d7ce97b4f1f40c82304d7444758307976307 | |
parent | c4b2dccd7db4126cab49fd4b2ec1545be5ba5ba6 (diff) | |
download | public-inbox-0795b0906cc81f400e0e5b9b53f812627dbd19c0.tar.gz |
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
-rw-r--r-- | lib/PublicInbox/DS.pm | 4 |
1 files changed, 3 insertions, 1 deletions
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(); |