Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Matts (1087)

Matts
  (email not shown publicly)

I work for MessageLabs [messagelabs.com] in Toronto, ON, Canada. I write spam filters, MTA software, high performance network software, string matching algorithms, and other cool stuff mostly in Perl and C.

Journal of Matts (1087)

Friday February 07, 2003
06:48 AM

Perl 5.8.0 signals and sockets

[ #10456 ]

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).

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • It's probably always good practice to set a flag in a signal handler to let the main flow of code know that something has happened...

    -Dom

    • Yes, but normally you'd do that like this:
      while (my $client = $server->accept()) {
         if ($SOMEFLAG) {
           ...
         }
         ...
      }
      Which doesn't work any more.
      • That's very true, and a subtle point for people who are used to looking at things one particular way; I quite glossed over that.

        Basically, you're saying that EINTR won't get reported properly and the system call won't get restarted either. Yuck.

        -Dom

        • Mostly it's for people reading the Perl Cookbook, which has the code the original way. I guess this'll all be fixed in Cookbook2, but until then I wanted to get something in google.