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

[PATCH] Full example of REAPER in perlipc #12124

Closed
p5pRT opened this issue May 21, 2012 · 13 comments
Closed

[PATCH] Full example of REAPER in perlipc #12124

p5pRT opened this issue May 21, 2012 · 13 comments

Comments

@p5pRT
Copy link

p5pRT commented May 21, 2012

Migrated from rt.perl.org#113028 (status was 'resolved')

Searchable as RT113028$

@p5pRT
Copy link
Author

p5pRT commented May 21, 2012

From worldmind@mail.ru

This is a bug report for perl from worldmind@​mail.ru,
generated with the help of perlbug 1.39 running under perl 5.14.2.

From d8632592e47bbd5b8e879732d9c5c288536fd169 Mon Sep 17 00​:00​:00 2001
From​: Alexey Shrub <worldmind@​mail.ru>
Date​: Mon, 21 May 2012 23​:06​:35 +0300
Subject​: [PATCH] Full example of REAPER in perlipc - we need loop for
process
  all signals (if some children exit in same time) and we
  need check reason of signal (no need process STOP signal
  see part 16.19. Avoiding Zombie Processes in "Perl
  Cookbook")


  pod/perlipc.pod | 14 ++++++++------
  1 file changed, 8 insertions(+), 6 deletions(-)

Inline Patch
diff --git a/pod/perlipc.pod b/pod/perlipc.pod
index 7650838..9b62a0f 100644
--- a/pod/perlipc.pod
+++ b/pod/perlipc.pod
@@ -117,18 +117,20 @@ therefore block.
  The best way to prevent this issue is to use waitpid(), as in the 
following   example​:

- use POSIX "​:sys_wait_h"; # for nonblocking read
+ use POSIX qw(​:signal_h :errno_h :sys_wait_h); # for nonblocking read

  my %children;

  $SIG{CHLD} = sub {
  # don't change $! and $? outside handler
  local ($!, $?);
- my $pid = waitpid(-1, WNOHANG);
- return if $pid == -1;
- return unless defined $children{$pid};
- delete $children{$pid};
- cleanup_child($pid, $?);
+ while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
+ next unless defined $children{$pid};
+ if ( WIFEXITED($?) or WIFSIGNALED($?) ) {
+ delete $children{$pid};
+ cleanup_child($pid, $?);
+ }
+ }
  };

  while (1) {
--
1.7.9.5


Flags​:
  category=docs
  severity=wishlist


Site configuration information for perl 5.14.2​:

Configured by Debian Project at Fri Mar 23 17​:14​:02 UTC 2012.

Summary of my perl5 (revision 5 version 14 subversion 2) configuration​:

  Platform​:
  osname=linux, osvers=2.6.24-31-server,
archname=x86_64-linux-gnu-thread-multi
  uname='linux allspice 2.6.24-31-server #1 smp tue feb 14 13​:12​:22
utc 2012 x86_64 x86_64 x86_64 gnulinux '
  config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN
-Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.14 -Darchlib=/usr/lib/perl/5.14
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.14.2
-Dsitearch=/usr/local/lib/perl/5.14.2 -Dman1dir=/usr/share/man/man1
-Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1
-Dsiteman3dir=/usr/local/man/man3 -Duse64bitint -Dman1ext=1
-Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm
-Uusesfio -Uusenm -Ui_libutil -DDEBUGGING=-g -Doptimize=-O2 -Duseshrplib
-Dlibperl=libperl.so.5.14.2 -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.6.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/x86_64-linux-gnu /lib/../lib
/usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /usr/lib
  libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt
  perllibs=-ldl -lm -lpthread -lc -lcrypt
  libc=, so=so, useshrplib=true, libperl=libperl.so.5.14.2
  gnulibc_version='2.15'
  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.14.2​:
  /etc/perl
  /usr/local/lib/perl/5.14.2
  /usr/local/share/perl/5.14.2
  /usr/lib/perl5
  /usr/share/perl5
  /usr/lib/perl/5.14
  /usr/share/perl/5.14
  /usr/local/lib/site_perl
  .


Environment for perl 5.14.2​:
  HOME=/home/worldmind42
  LANG=ru_RU.UTF-8
  LANGUAGE (unset)
  LD_LIBRARY_PATH (unset)
  LOGDIR (unset)

PATH=/home/worldmind42/bin​:/usr/lib/lightdm/lightdm​:/usr/local/sbin​:/usr/local/bin​:/usr/sbin​:/usr/bin​:/sbin​:/bin​:/usr/games
  PERL_BADLANG (unset)
  SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

From @cpansprout

On Mon May 21 13​:33​:30 2012, worldmind@​mail.ru wrote​:

This is a bug report for perl from worldmind@​mail.ru,
generated with the help of perlbug 1.39 running under perl 5.14.2.

From d8632592e47bbd5b8e879732d9c5c288536fd169 Mon Sep 17 00​:00​:00 2001
From​: Alexey Shrub <worldmind@​mail.ru>
Date​: Mon, 21 May 2012 23​:06​:35 +0300
Subject​: [PATCH] Full example of REAPER in perlipc - we need loop for
process
all signals (if some children exit in same time) and we
need check reason of signal (no need process STOP signal
see part 16.19. Avoiding Zombie Processes in "Perl
Cookbook")

---
pod/perlipc.pod | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/pod/perlipc.pod b/pod/perlipc.pod
index 7650838..9b62a0f 100644
--- a/pod/perlipc.pod
+++ b/pod/perlipc.pod
@​@​ -117,18 +117,20 @​@​ therefore block.
The best way to prevent this issue is to use waitpid(), as in the
following
example​:

- use POSIX "​:sys_wait_h"; # for nonblocking read
+ use POSIX qw(​:signal_h :errno_h :sys_wait_h); # for nonblocking read

  my %children;

  $SIG\{CHLD\} = sub \{
      \# don't change $\! and $? outside handler
      local \($\!\, $?\);

- my $pid = waitpid(-1, WNOHANG);
- return if $pid == -1;
- return unless defined $children{$pid};
- delete $children{$pid};
- cleanup_child($pid, $?);
+ while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
+ next unless defined $children{$pid};
+ if ( WIFEXITED($?) or WIFSIGNALED($?) ) {
+ delete $children{$pid};
+ cleanup_child($pid, $?);
+ }
+ }
};

  while \(1\) \{

Tom, can you comment on this?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

From [Unknown Contact. See original ticket]

On Mon May 21 13​:33​:30 2012, worldmind@​mail.ru wrote​:

This is a bug report for perl from worldmind@​mail.ru,
generated with the help of perlbug 1.39 running under perl 5.14.2.

From d8632592e47bbd5b8e879732d9c5c288536fd169 Mon Sep 17 00​:00​:00 2001
From​: Alexey Shrub <worldmind@​mail.ru>
Date​: Mon, 21 May 2012 23​:06​:35 +0300
Subject​: [PATCH] Full example of REAPER in perlipc - we need loop for
process
all signals (if some children exit in same time) and we
need check reason of signal (no need process STOP signal
see part 16.19. Avoiding Zombie Processes in "Perl
Cookbook")

---
pod/perlipc.pod | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/pod/perlipc.pod b/pod/perlipc.pod
index 7650838..9b62a0f 100644
--- a/pod/perlipc.pod
+++ b/pod/perlipc.pod
@​@​ -117,18 +117,20 @​@​ therefore block.
The best way to prevent this issue is to use waitpid(), as in the
following
example​:

- use POSIX "​:sys_wait_h"; # for nonblocking read
+ use POSIX qw(​:signal_h :errno_h :sys_wait_h); # for nonblocking read

  my %children;

  $SIG\{CHLD\} = sub \{
      \# don't change $\! and $? outside handler
      local \($\!\, $?\);

- my $pid = waitpid(-1, WNOHANG);
- return if $pid == -1;
- return unless defined $children{$pid};
- delete $children{$pid};
- cleanup_child($pid, $?);
+ while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
+ next unless defined $children{$pid};
+ if ( WIFEXITED($?) or WIFSIGNALED($?) ) {
+ delete $children{$pid};
+ cleanup_child($pid, $?);
+ }
+ }
};

  while \(1\) \{

Tom, can you comment on this?

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

@cpansprout - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented May 22, 2012

From @Leont

On Mon, May 21, 2012 at 10​:33 PM, Alexey Shrub
<perlbug-followup@​perl.org> wrote​:

From​: Alexey Shrub <worldmind@​mail.ru>
Subject​: [PATCH] Full example of REAPER in perlipc - we need loop for
process
 all signals (if some children exit in same time) and we
 need check reason of signal (no need process STOP signal
 see part 16.19. Avoiding Zombie Processes in "Perl
 Cookbook")

Good point. This is the kind of pitfall that should probable be
explained in perlipc.

Leon

@p5pRT
Copy link
Author

p5pRT commented May 25, 2012

From @Leont

On Tue, May 22, 2012 at 5​:05 PM, Leon Timmermans <fawaka@​gmail.com> wrote​:

Good point. This is the kind of pitfall that should probable be
explained in perlipc.

On second reading, that does not seem necessary. The process will
receive a sigchild under these circumstances, but waitpid will ignore
that status unless asked for it (using the WUNTRACED and WCONTINUE
options).

Leon

@p5pRT
Copy link
Author

p5pRT commented May 25, 2012

From worldmind@mail.ru

Птн. Май 25 04​:21​:50 2012, LeonT писал​:

On Tue, May 22, 2012 at 5​:05 PM, Leon Timmermans <fawaka@​gmail.com>
On second reading, that does not seem necessary. The process will
receive a sigchild under these circumstances, but waitpid will ignore
that status unless asked for it (using the WUNTRACED and WCONTINUE
options).

As I understand you say that we can skip WIFEXITED($?) and
WIFSIGNALED($?) checking, but we will get STOP signal and process it
like child exiting.
Simple example in attached file​:
1. Run
perl fork-test.pl

ps aux | grep fork-test.pl
1000 6093 0.2 0.2 31716 4004 pts/2 S+ 16​:00 0​:00 perl
fork-test.pl
1000 6100 0.0 0.1 31716 2244 pts/2 S+ 16​:00 0​:00 perl
fork-test.pl
1000 6102 0.0 0.0 14824 948 pts/3 S+ 16​:00 0​:00 grep
--color=auto fork-test.pl

2. Send STOP signal to child
kill -s STOP 6100

we got warn message 'Get CHLD signal at fork-test.pl line 7.'

STOP signal it is not exit - process can continue working after CONT signal

@p5pRT
Copy link
Author

p5pRT commented May 25, 2012

From worldmind@mail.ru

fork-test.pl

@p5pRT
Copy link
Author

p5pRT commented Jun 24, 2013

From @tonycoz

On Fri May 25 06​:08​:13 2012, worldmind wrote​:

Птн. Май 25 04​:21​:50 2012, LeonT писал​:

On Tue, May 22, 2012 at 5​:05 PM, Leon Timmermans <fawaka@​gmail.com>
On second reading, that does not seem necessary. The process will
receive a sigchild under these circumstances, but waitpid will ignore
that status unless asked for it (using the WUNTRACED and WCONTINUE
options).

As I understand you say that we can skip WIFEXITED($?) and
WIFSIGNALED($?) checking, but we will get STOP signal and process it
like child exiting.
Simple example in attached file​:

I don't think this answers Leon's objection - waitpid() will only return
the child process id on a STOP if you supply WUNTRACED in options.

If you modify your code to check waitpid​:

$SIG{CHLD} = sub {
  my $pid = waitpid(-1, WNOHANG);
  if ($pid > 0) {
  warn 'Get CHLD signal ', $pid;
  }
};

then you don't get the warning on a STOP.

That said, the waitpid() loop is required (which the cookbook doesn't
seem to use.)

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

On Fri May 25 04​:21​:50 2012, LeonT wrote​:

On Tue, May 22, 2012 at 5​:05 PM, Leon Timmermans <fawaka@​gmail.com> wrote​:

Good point. This is the kind of pitfall that should probable be
explained in perlipc.

On second reading, that does not seem necessary. The process will
receive a sigchild under these circumstances, but waitpid will ignore
that status unless asked for it (using the WUNTRACED and WCONTINUE
options).

I've attached a simplified patch that changes the single waitpid() call
to a loop without the WIF*() checks from the original patch.

Looking at the text around that example, I wonder if this example could
be consolidated with the example above it, which already used a
waitpid() loop.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 12, 2013

From @tonycoz

0001-perl-113028-handle-multiple-children-exiting-in-perl.patch
From 734b0722f62d7141a53d8389bc39dc9181581da9 Mon Sep 17 00:00:00 2001
From: Tony Cook <tony@develop-help.com>
Date: Fri, 12 Jul 2013 17:12:46 +1000
Subject: [PATCH] [perl #113028] handle multiple children exiting in perlipc
 example

---
 pod/perlipc.pod |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/pod/perlipc.pod b/pod/perlipc.pod
index 69567e9..decb59b 100644
--- a/pod/perlipc.pod
+++ b/pod/perlipc.pod
@@ -124,11 +124,10 @@ example:
     $SIG{CHLD} = sub {
         # don't change $! and $? outside handler
         local ($!, $?);
-        my $pid = waitpid(-1, WNOHANG);
-        return if $pid == -1;
-        return unless defined $children{$pid};
-        delete $children{$pid};
-        cleanup_child($pid, $?);
+        while ( (my $pid = waitpid(-1, WNOHANG)) > 0 ) {
+            delete $children{$pid};
+            cleanup_child($pid, $?);
+        }
     };
 
     while (1) {
-- 
1.7.10.4

@p5pRT
Copy link
Author

p5pRT commented Jul 19, 2013

From @tonycoz

On Fri Jul 12 00​:16​:11 2013, tonyc wrote​:

On Fri May 25 04​:21​:50 2012, LeonT wrote​:

On Tue, May 22, 2012 at 5​:05 PM, Leon Timmermans <fawaka@​gmail.com>
wrote​:

Good point. This is the kind of pitfall that should probable be
explained in perlipc.

On second reading, that does not seem necessary. The process will
receive a sigchild under these circumstances, but waitpid will ignore
that status unless asked for it (using the WUNTRACED and WCONTINUE
options).

I've attached a simplified patch that changes the single waitpid() call
to a loop without the WIF*() checks from the original patch.

Looking at the text around that example, I wonder if this example could
be consolidated with the example above it, which already used a
waitpid() loop.

Applied as fd44020.

Tony

@p5pRT
Copy link
Author

p5pRT commented Jul 26, 2013

@tonycoz - Status changed from 'open' to 'resolved'

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

1 participant