develooper Front page | perl.perl5.porters | Postings from July 2019

[perl #126474] malloc deadlock in unsafe signal handler

Thread Next
From:
Tony Cook via RT
Date:
July 10, 2019 01:48
Subject:
[perl #126474] malloc deadlock in unsafe signal handler
Message ID:
rt-4.0.24-28295-1562723317-1991.126474-15-0@perl.org
On Sun, 08 Nov 2015 19:43:06 -0800, tonyc wrote:
> On Thu Oct 29 19:27:04 2015, kazuhooku@gmail.com wrote:
> > For example, you can call POSIX::write in the unsafe signal handler
> > to
> > wake up `select` reliably.  The code will look like:
> >
> > pipe(my $rfh, $wfh);
> > my $wfd = fileno $wfh;
> > POSIX::sigaction(SIGTERM, POSIX::SigAction->new(sub {
> >     POSIX::write $wfd, "1", 1;
> 
> POSIX::write() calls sv_newmortal() for its return value, so there's a
> small change of a call to malloc() there.

Both for allocating the SV itself and for expanding the tmps stack.

> 
> > }));
> >
> > my $rbits = '';
> > vec($rbits, fileno $rfh, 1) = 1;
> > ...
> > select($rbits, ...);
> >
> > This is essentially same as using signaled provided by Linux, but is
> > more portable.
> >
> > >> However (as I believe) in Perl 5.17, the implementation of the
> > >> signal
> > >> handler in the perl core has been altered to _always_ call malloc
> > >> (via
> > >> newSVsv).
> > >>
> > >> In other words, starting from 5.17, it has become _impossible_ to
> > >> write an unsafe signal handler without fear of deadlock.  And that
> > >> is
> > >> what I see as a regression.
> > >>
> > >
> > > I think you're referring to 100c03aa. Possibly an alternative $@ is
> > > the
> > > solution here too.
> >
> > Agreed.
> 
> Possibly $@ should be set to a sv_newmortal() instead of a copy of its
> current value.

That doesn't help, the CLEAR_ERRSV() in Perl_call_sv() will still allocate a new PV (via SvPVCLEAR() which is a wrapper around Perl_sv_setpv_bufsize()).

Several other macros can end up allocating memory too, depending on whether the stack involved has enough space or not.

We can't use G_KEEPERR to skip the CLEAR_ERRSV() since the signal handler uses the value of ERRSV to check if the sub died.

The only way I can see to make it work would be to pre-create a SV that we keep in an interpreter global and substitute that into GvSV(PL_errgv) when we call_sv() the signal handler.

This doesn't prevent all of the other potential allocations.

Tony

Tony

---
via perlbug:  queue: perl5 status: open
https://rt.perl.org/Ticket/Display.html?id=126474

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About