in reply to Re: Re: Net::Daemon and zombies
in thread Net::Daemon and zombies

That code is buggy. Here it is in a package with a dummy new function, a warn statement to tell us when the reaper is running, and the line that checks if we're running under Linux commented out (since I'm testing it on Linux):
#!/usr/bin/perl -w use strict; my $nd = NDTest->new; $nd->Bind; warn "My PID is $$\n"; foreach my $i (1..10) { if (!fork()) { # Child sleep(1); exit($i); } sleep(2); } package NDTest; sub new { my $class = shift; my $self = {}; $self->{mode} = 'fork'; bless $self,$class; } sub SigChildHandler { my $self = shift; my $ref = shift; return undef if $self->{'mode'} ne 'fork'; # Don't care for childs +. # return 'IGNORE' if $^O eq 'linux'; # We get zombies on Linux othe +rwise my $reaper; sub { warn "Running reaper.\n"; $$ref = wait; $SIG{'CHLD'} = $reaper; }; } sub Bind ($) { my $self = shift; my $fh; my $child_pid; my $reaper = $self->SigChildHandler(\$child_pid); $SIG{'CHLD'} = $reaper if $reaper; }
That creates 10 children fairly slowly. Let's see how many are reaped:
[sgifford@sghome pa1]$ perl /tmp/t107 My PID is 18286 Running reaper. Use of uninitialized value in scalar assignment at /tmp/t107 line 37.
That doesn't look promising. So what happened to the other 9 processes?
$ ps -ef |grep 18286 sgifford 18286 16547 0 14:02 pts/0 00:00:00 perl /tmp/t107 sgifford 18288 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18289 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18292 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18295 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18298 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18301 18286 0 14:02 pts/0 00:00:00 [perl <defunct>] sgifford 18303 18212 0 14:03 pts/20 00:00:00 grep 18286
Yup. Zombies. Just like you're seeing.

I think that the only problem with this code is a typo. If we add a line below my $reaper;, saying $reaper =, assigning the sub ref to $reaper (which is what I believe the author intended) the problem goes away.

#!/usr/bin/perl -w use strict; my $nd = NDTest->new; $nd->Bind; warn "My PID is $$\n"; foreach my $i (1..10) { if (!fork()) { # Child sleep(1); exit($i); } sleep(2); } package NDTest; sub new { my $class = shift; my $self = {}; $self->{mode} = 'fork'; bless $self,$class; } sub SigChildHandler { my $self = shift; my $ref = shift; return undef if $self->{'mode'} ne 'fork'; # Don't care for childs +. # return 'IGNORE' if $^O eq 'linux'; # We get zombies on Linux othe +rwise my $reaper; $reaper = sub { warn "Running reaper.\n"; $$ref = wait; $SIG{'CHLD'} = $reaper; }; } sub Bind ($) { my $self = shift; my $fh; my $child_pid; my $reaper = $self->SigChildHandler(\$child_pid); $SIG{'CHLD'} = $reaper if $reaper; }
$ perl /tmp/t107 My PID is 18322 Running reaper. Running reaper. Running reaper. Running reaper. Running reaper. Running reaper. Running reaper. Running reaper. Running reaper. Running reaper.