A friend asked me about this problem, and I am stuck, so I'm asking for your help. The following code is taken almost directly from chapter 12 of Advanced Perl Programming (under "Handling Multiple Clients -Multiple Threads of Execution").
When I test it by telnetting to port 7070, it works correctly, printing back what I type. But when I close the connection, the server program exits. Some examination seems to indicate that the accept() call is not being restarted after the signal handler returns. If I set the signal handler to 'IGNORE', everything works ok, which is good for our purposes, but now I am curious as to why this does not work.# Forking server use IO::Socket; use POSIX; sub REAPER { my $stiff; while( $stiff=waitpid(-1,WNOHANG)>0) { } $SIG{CHLD}=\&REAPER; } $SIG{CHLD} = \&REAPER; $main_sock = new IO::Socket::INET (LocalHost => 'localhost', LocalPort => 7070, Listen => 5, Proto => 'tcp', Reuse => 1, ); die "Error: $!\n" unless ($main_sock); while ($new_sock = $main_sock->accept()) { $pid = fork(); die "Cannot fork: $!" unless defined($pid); if ($pid == 0) { # Child process while (defined($buf = <$new_sock>)) { # do something with $buf .... print $new_sock "You said: $buf\n"; } exit(0); # Child process exits when it is done. } else { # Close new socket in the parent $new_sock->close; } } close ($main_sock);
I also tried explicitly setting the SA_RESTART flag on the SIGCHLD signal, so that it restarts interrupted slow system calls. So I replaced the assignment to $SIG{CHLD} with the following:
But I get the exact same behavior. I am on Solaris 2.7, with perl 5.005. Any ideas?$sigset=POSIX::SigSet->new(SIGCHLD); $sigaction=POSIX::SigAction->new('main::REAPER', $sigset, &POSIX::SA_R +ESTART); $osigact=POSIX::SigAction->new; sigaction(SIGCHLD, $sigaction, $osigact);
Thanks,
--ZZamboni
In reply to SIGCHLD interrupting accept call? by ZZamboni
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |