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

EAGAIN on fork failure is retried forever #12178

Open
p5pRT opened this issue Jun 15, 2012 · 4 comments
Open

EAGAIN on fork failure is retried forever #12178

p5pRT opened this issue Jun 15, 2012 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 15, 2012

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

Searchable as RT113668$

@p5pRT
Copy link
Author

p5pRT commented Jun 15, 2012

From @porridge

This is a bug report for perl from marcin@​owsiany.pl,
generated with the help of perlbug 1.39 running under perl 5.10.1.


Reproduce with​:

$ cat <<END > t
#!/usr/bin/perl
open T,"./t|" or die $!; <T>
END
$ chmod +x t
$ (ulimit -u 254; LANG=C ./t)

Expected behaviour​:
- a chain of processes is created, once the limit is reached, the open fails
  in the youngest child, and they all terminate in reverse order.

Actual behaviour​:
- a chain of processes is indeed created​:

32315 pts/0 S 0​:00 /usr/bin/perl ./t
32316 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32317 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32318 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32319 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32320 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32321 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32322 pts/0 S 0​:00 \_ /usr/bin/perl ./t
32323 pts/0 S 0​:00 \_ /usr/bin/perl ./t

- however once the limit is reached, the youngest child enters an infinite
  loop retrying the fork. Running strace shows a the following in a loop​:

  restart_syscall(<... resuming interrupted call ...>) = 0
  clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f5a94d959d0) = -1 EAGAIN (Resource temporarily unavailable)
  rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
  rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
  rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
  nanosleep({5, 0}, 0x7ffff9974210) = 0
 
- this is not very useful behaviour, because if an unprivileged user
  accidentally gets into this situation, he is locked out of the system. Perl
  should instead retry a few times and then back off.

I had a quick look and I can see code that can cause this in the following places​:

pp_sys.c- while ((childpid = PerlProc_fork()) == -1) {
pp_sys.c​: if (errno != EAGAIN) {
pp_sys.c- value = -1;
pp_sys.c- SP = ORIGMARK;
pp_sys.c- XPUSHi(value);
pp_sys.c- if (did_pipes) {
pp_sys.c- PerlLIO_close(pp[0]);
pp_sys.c- PerlLIO_close(pp[1]);
pp_sys.c- }
pp_sys.c-#if (defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO))
pp_sys.c- sigprocmask(SIG_SETMASK, &oldset, NULL);
pp_sys.c-#endif
pp_sys.c- RETURN;
pp_sys.c- }
pp_sys.c- sleep(5);
pp_sys.c- }

util.c- while ((pid = PerlProc_fork()) < 0) {
util.c​: if (errno != EAGAIN) {
util.c- PerlLIO_close(p[This]);
util.c- PerlLIO_close(p[that]);
util.c- if (did_pipes) {
util.c- PerlLIO_close(pp[0]);
util.c- PerlLIO_close(pp[1]);
util.c- }
util.c- return NULL;
util.c- }
util.c- Perl_ck_warner(aTHX_ packWARN(WARN_PIPE), "Can't fork, trying again in 5 seconds");
util.c- sleep(5);
util.c- }

util.c- while ((pid = PerlProc_fork()) < 0) {
util.c​: if (errno != EAGAIN) {
util.c- PerlLIO_close(p[This]);
util.c- PerlLIO_close(p[that]);
util.c- if (did_pipes) {
util.c- PerlLIO_close(pp[0]);
util.c- PerlLIO_close(pp[1]);
util.c- }
util.c- if (!doexec)
util.c- Perl_croak(aTHX_ "Can't fork​: %s", Strerror(errno));
util.c- return NULL;
util.c- }
util.c- Perl_ck_warner(aTHX_ packWARN(WARN_PIPE), "Can't fork, trying again in 5 seconds");
util.c- sleep(5);
util.c- }

Here is how bash deals with the same problem for example​:

$ (ulimit -u 1; LANG=C ./t)
bash​: fork​: retry​: Resource temporarily unavailable
bash​: fork​: retry​: Resource temporarily unavailable
bash​: fork​: retry​: Resource temporarily unavailable
bash​: fork​: retry​: Resource temporarily unavailable
bash​: fork​: Resource temporarily unavailable
Terminated



Flags​:
  category=core
  severity=medium


Site configuration information for perl 5.10.1​:

Configured by Debian Project at Fri Apr 22 18​:53​:20 UTC 2011.

Summary of my perl5 (revision 5 version 10 subversion 1) configuration​:
 
  Platform​:
  osname=linux, osvers=2.6.24-28-server, archname=x86_64-linux-gnu-thread-multi
  uname='linux allspice 2.6.24-28-server #1 smp wed aug 18 21​:17​:51 utc 2010 x86_64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.10 -Darchlib=/usr/lib/perl/5.10 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.10.1 -Dsitearch=/usr/local/lib/perl/5.10.1 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib -Dlibperl=libperl.so.5.10.1 -Dd_dosuid -des'
  hint=recommended, useposix=true, d_sigaction=define
  useithreads=define, usemultiplicity=define
  useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
  use64bitint=define, use64bitall=define, uselongdouble=undef
  usemymalloc=n, bincompat5005=undef
  Compiler​:
  cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
  optimize='-O2 -g',
  cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
  ccversion='', gccversion='4.4.3', gccosandvers=''
  intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
  d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
  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 /lib /usr/lib /lib64 /usr/lib64
  libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
  perllibs=-ldl -lm -lpthread -lc -lcrypt
  libc=/lib/libc-2.11.1.so, so=so, useshrplib=true, libperl=libperl.so.5.10.1
  gnulibc_version='2.11.1'
  Dynamic Linking​:
  dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
  cccdlflags='-fPIC', lddlflags='-shared -O2 -g -L/usr/local/lib -fstack-protector'

Locally applied patches​:
 


@​INC for perl 5.10.1​:
  /etc/perl
  /usr/local/lib/perl/5.10.1
  /usr/local/share/perl/5.10.1
  /usr/lib/perl5
  /usr/share/perl5
  /usr/lib/perl/5.10
  /usr/share/perl/5.10
  /usr/local/lib/site_perl
  .


Environment for perl 5.10.1​:
  HOME=/home/mowsiany
  LANG=pl_PL.utf8
  LANGUAGE (unset)
  LC_COLLATE=C
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)
  PATH=/home/mowsiany/bin​:/home/mowsiany/bin​:/usr/local/sbin​:/usr/local/bin​:/usr/sbin​:/usr/bin​:/sbin​:/bin
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Jun 17, 2012

From @chipdude

Seems to me that EAGAIN should not actually be retried at all, in this case.

@p5pRT
Copy link
Author

p5pRT commented Jun 17, 2012

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

@p5pRT
Copy link
Author

p5pRT commented Jun 20, 2012

From @Leont

On Sun, Jun 17, 2012 at 8​:00 AM, Chip Salzenberg <rev.chip@​gmail.com> wrote​:

Seems to me that EAGAIN should not actually be retried at all, in this case.

I agree that would be a more sensible approach. Let the user deal with
their own form bomb.

Leon

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

No branches or pull requests

2 participants