This week I've been dreading the approach of a co-worker because he's had problems with a socket server on perl 5.8.0 that works fine on 5.6.1 and below. The problem was that the CHLD signal handler was causing the program to exit, rather than just reaping the child.
The problem looks something like this:
$SIG{CHLD} = \&REAPER;
my $server = _mk_sock();
while (my $client = $server->accept) {
my $pid = fork();
die "fork failed" unless defined $pid;
if ($pid) {
# parent
next;
}
# child
...
}
Now this works beautifully under perls before 5.8.0, but with 5.8.0's safe signals it breaks.
Unfortunately it appears that very few people have experienced this problem on google groups or elsewhere, so we had to figure it out for ourselves...
What's happening is that safe signals break out of the accept() call and execute the REAPER, but they don't go back into the accept() call like non-safe signals would - they make the accept() call return false. This is logical if you think about it, but took us many brane stroking hours to figure out.
Anyway, the solution is:
sub REAPER {
...
$CHILDEXIT = 1;
}
...
while (1) {
my $client = $server->accept;
if ($CHILDEXIT) {
$CHILDEXIT = 0;
next;
}
elsif (!$client) {
die "accept failed";
}
...
}
There was something mentioned on usenet about EINTR but the above works fine.
(The main point of writing this journal entry is so that google indexes it to help others with similar problems).
Good Practice (Score:1)
-Dom
Re:Good Practice (Score:2)
Re:Good Practice (Score:1)
Basically, you're saying that EINTR won't get reported properly and the system call won't get restarted either. Yuck.
-Dom
Re:Good Practice (Score:2)