Out of memory when doing IO via pipe and receive signal #16960
This is a bug report for perl from email@example.com,
Out of memory error (ENOMEN) can occur when Perl is doing IO via pipe and a signal handler is triggered.
Test codes to reproduce the problem can be found here:
Perl will fail to run at least one of 'perlio-signal-while-safe.pl' and 'perlio-signal-while.pl'.
Serveral Perl versions are affected including 5.16.1, 5.18.2, 5.26.1.
Some crash logs (perl 5.18.2, macos):
# perl perlio-signal-while.pl
Some gdb results (perl 5.16.1, linux):
(gdb) run perlio-signal-while.pl
Breakpoint 1, Perl_sv_gets (sv=0x780ca0, fp=0x76ee90, append=0) at sv.c:7821
Breakpoint 1, Perl_sv_gets (sv=0x780c28, fp=0x76ee70, append=0) at sv.c:7821
(gdb) p ptr
(gdb) p bp
(gdb) p ((const char*)((sv)->sv_u.svu_pv))
Site configuration information for perl 5.26.1:
Configured by Ubuntu at Mon Nov 19 15:54:44 UTC 2018.
Summary of my perl5 (revision 5 version 26 subversion 1) configuration:
Locally applied patches:
@INC for perl 5.26.1:
Environment for perl 5.26.1:
On Mon, 15 Apr 2019 21:18:40 -0700, firstname.lastname@example.org wrote:
Yeah, the code isn't expecting the SV, $_ in this case, to be modified from underneath it.
to the beginning of the signal handler also fixes the problem and is probably the sane thing to do in a signal handler anyway.
Having perl do the local would fix it for $_, but it would still be broken for any other SV.
The attached patch fixes it for me.
$ ../perl/perl -I../perl/lib perlio-signal-while-safe.pl
At first I thought it might be a safe signals problem, but that isn't the case.
From fb09f9d42c2557570354463dc2299ca2e7f0fc41 Mon Sep 17 00:00:00 2001 From: Tony Cook <email@example.com> Date: Wed, 17 Apr 2019 15:45:15 +1000 Subject: (perl #134035) ensure sv_gets() handles a signal handler modifying sv At a very basic level at least. In the ticket cases, a signal handler is modifying (and reallocating PVX) the sv, while sv_gets() retained a pointer to the inside of the SV. This still has some problems, like if the signal handler ends up shortening SV, there may be old data left between the old position and the new position, but I think that's a case of user error. --- sv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sv.c b/sv.c index 9b659e8c16..99998b1d0e 100644 --- a/sv.c +++ b/sv.c @@ -8755,7 +8755,10 @@ Perl_sv_gets(pTHX_ SV *const sv, PerlIO *const fp, I32 append) Note we have to deal with the char in 'i' if we are not at EOF */ + bpx = bp - (STDCHAR*)SvPVX_const(sv); + /* signals might be called here, possibly modifying sv */ i = PerlIO_getc(fp); /* get more characters */ + bp = (STDCHAR*)SvPVX_const(sv) + bpx; DEBUG_Pv(PerlIO_printf(Perl_debug_log, "Screamer: post: FILE * thinks ptr=%" UVuf ", cnt=%" IVdf ", base=%" UVuf "\n", -- 2.11.0