Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

system() does not return -1 in low-memory situations #15890

Open
p5pRT opened this issue Feb 24, 2017 · 5 comments
Open

system() does not return -1 in low-memory situations #15890

p5pRT opened this issue Feb 24, 2017 · 5 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 24, 2017

Migrated from rt.perl.org#130853 (status was 'open')

Searchable as RT130853$

@p5pRT
Copy link
Author

p5pRT commented Feb 24, 2017

From srezic@cpan.org

This is a bug report for perl from srezic@​cpan.org,
generated with the help of perlbug 1.40 running under perl 5.22.2.


If system() fails because there's not enough memory, then the
return value or the value of $? is still zero.

This can be reproduced with the following script (call with
somewhat more than half of the available memory in gigabytes
on linux systems (this is another problem which will get another
issue))​:

#!/usr/bin/perl

use strict;
use Test​::More 'no_plan';

my $alloc_gb = shift || 4;

my $mb = " " x 1024**2;
my $buf;
for (1..$alloc_gb*1024) {
  $buf .= $mb;
}

system 'echo', 'system() was successful';
is $?, -1
  or diag "Return values of system() call​: \$?=$?, \$!=$!";

__END__

$! will be ENOMEM here, but $? is 0.

The problem can be reproduced on travis-ci instances. See the
build logs here​: https://travis-ci.org/eserte/sandbox/builds/205016073
(disregard the 5.6.2 entry, there's no perl 5.6.2 at travis-ci)

Regards,
  Slaven



Flags​:
  category=core
  severity=medium


Site configuration information for perl 5.22.2​:

Configured by slaven.rezic at Fri May 13 10​:07​:27 CEST 2016.

Summary of my perl5 (revision 5 version 22 subversion 2) configuration​:
 
  Platform​:
  osname=linux, osvers=3.2.0-57-generic, archname=x86_64-linux
  uname='linux ws40601 3.2.0-57-generic #87-ubuntu smp tue nov 12 21​:35​:10 utc 2013 x86_64 x86_64 x86_64 gnulinux '
  config_args='-ds -e -Dprefix=/opt/perl-5.22.2 -Dcf_email=srezic@​cpan.org'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=undef, usemultiplicity=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2',
  cppflags='-fwrapv -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.6.3', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678, doublekind=3
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16, longdblkind=3
  ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
  alignbytes=8, prototype=define
  Linker and Libraries​:
  ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
  libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/4.6/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib
  libs=-lpthread -lnsl -ldb -ldl -lm -lcrypt -lutil -lc
  perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
  libc=libc-2.15.so, so=so, useshrplib=false, libperl=libperl.a
  gnulibc_version='2.15'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector'


@​INC for perl 5.22.2​:
  /opt/perl-5.22.2/lib/site_perl/5.22.2/x86_64-linux
  /opt/perl-5.22.2/lib/site_perl/5.22.2
  /opt/perl-5.22.2/lib/5.22.2/x86_64-linux
  /opt/perl-5.22.2/lib/5.22.2
  .


Environment for perl 5.22.2​:
  HOME=/home/slaven.rezic
  LANG=de_DE.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/usr/local/bin​:/usr/bin​:/bin​:/usr/local/sbin​:/usr/sbin​:/sbin​:/home/slaven.rezic/bin/linux-gnu​:/home/slaven.rezic/bin/sh​:/home/slaven.rezic/bin​:/home/slaven.rezic/bin/pistachio-perl/bin​:/usr/games​:/home/slaven.rezic/devel​:/home/slaven.rezic/work/drafts-slaven.rezic/misc
  PERLDOC=-MPod​::Perldoc​::ToTextOverstrike
  PERL_BADLANG (unset)
  SHELL=/usr/bin/zsh

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2017

From @tonycoz

On Fri, 24 Feb 2017 08​:26​:03 -0800, srezic@​cpan.org wrote​:

If system() fails because there's not enough memory, then the
return value or the value of $? is still zero.

This can be reproduced with the following script (call with
somewhat more than half of the available memory in gigabytes
on linux systems (this is another problem which will get another
issue))​:

#!/usr/bin/perl

use strict;
use Test​::More 'no_plan';

my $alloc_gb = shift || 4;

my $mb = " " x 1024**2;
my $buf;
for (1..$alloc_gb*1024) {
$buf .= $mb;
}

system 'echo', 'system() was successful';
is $?, -1
or diag "Return values of system() call​: \$?=$?, \$!=$!";

__END__

$! will be ENOMEM here, but $? is 0.

The problem can be reproduced on travis-ci instances. See the
build logs here​: https://travis-ci.org/eserte/sandbox/builds/205016073
(disregard the 5.6.2 entry, there's no perl 5.6.2 at travis-ci)

I'm not really set up to test this, but the attached sets $? on the path where
fork fails, please let me know if this fixes the problem for you.

Tony

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2017

From @tonycoz

0001-perl-130853-ensure-system-sets-even-if-fork-fails.patch
From f4c92c68052e313ebfb6c7bc48081ece7492ffdf Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Mon, 27 Feb 2017 14:23:34 +1100
Subject: (perl #130853) ensure system() sets $? even if fork() fails

The documentation implies $? is always set.
---
 pp_sys.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pp_sys.c b/pp_sys.c
index 7a57035..6ccaad7 100644
--- a/pp_sys.c
+++ b/pp_sys.c
@@ -4397,6 +4397,7 @@ PP(pp_system)
 		    PerlLIO_close(pp[0]);
 		    PerlLIO_close(pp[1]);
 		}
+                STATUS_NATIVE_CHILD_SET(value);
 #ifdef HAS_SIGPROCMASK
 		sigprocmask(SIG_SETMASK, &oldset, NULL);
 #endif
-- 
2.1.4

@p5pRT
Copy link
Author

p5pRT commented Feb 27, 2017

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Mar 1, 2017

From @eserte

Dana Sun, 26 Feb 2017 19​:26​:14 -0800, tonyc reče​:

On Fri, 24 Feb 2017 08​:26​:03 -0800, srezic@​cpan.org wrote​:

If system() fails because there's not enough memory, then the
return value or the value of $? is still zero.

This can be reproduced with the following script (call with
somewhat more than half of the available memory in gigabytes
on linux systems (this is another problem which will get another
issue))​:

#!/usr/bin/perl

use strict;
use Test​::More 'no_plan';

my $alloc_gb = shift || 4;

my $mb = " " x 1024**2;
my $buf;
for (1..$alloc_gb*1024) {
$buf .= $mb;
}

system 'echo', 'system() was successful';
is $?, -1
or diag "Return values of system() call​: \$?=$?, \$!=$!";

__END__

$! will be ENOMEM here, but $? is 0.

The problem can be reproduced on travis-ci instances. See the
build logs here​: https://travis-
ci.org/eserte/sandbox/builds/205016073
(disregard the 5.6.2 entry, there's no perl 5.6.2 at travis-ci)

I'm not really set up to test this, but the attached sets $? on the
path where
fork fails, please let me know if this fixes the problem for you.

Yes, this fixes the problem.

Unpatched perl​:

$ perl5.25.9 /tmp/mem.pl 8
not ok 1
# Failed test at /tmp/mem.pl line 15.
# got​: '0'
# expected​: '-1'
# Return values of system() call​: $?=0, $!=Cannot allocate memory
1..1
# Looks like you failed 1 test of 1.

Patched on top of fe7d7ed​:

$ ./perl -Ilib /tmp/mem.pl 8
ok 1
1..1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants