powerman has asked for the wisdom of the Perl Monks concerning the following question:

Is anybody knows why adding flag SA_RESTART to signal handler will block signal receiving in sysread() at all?

And how to create signal handler which will continue processing signals without interrupting system calls with EINTR?

use POSIX; $SIG = 10; $SIGNAME = "USR1"; #$SIG = 50; $SIGNAME = "NUM50"; $SIG{$SIGNAME} = sub { $got++ }; sigaction($SIG, undef, my $act=bless({}, "POSIX::SigAction")); $act->{FLAGS} |= &POSIX::SA_RESTART; sigaction($SIG, $act); my $parent_pid = $$; die "can't fork\n" unless defined(my $chield_pid = fork()); unless ($chield_pid) { select(undef,undef,undef, 0.1), kill($SIG, $parent_pid) while 1; } my $n = sysread \*STDIN, my $buf, 1; printf "got=%d n=%s err=%s\n", $got, defined($n) ? $n : "undef", $!; kill 9, $chield_pid;

Replies are listed 'Best First'.
Re: Signals, SA_RESTART, and EINTR
by matija (Priest) on Apr 19, 2004 at 06:43 UTC
    I assume you're running a recent Perl, with safe signals. That means that Perl will act on a signal only between perlops, not during.(Why? Because signals which arrive while perl is busy during a perlop could cause mayhem - perl's internals could be in an inconsistent state, so a complicated handler could easily cause a crash. The usual cure was to keep signal handlers very, very simple, but it still wasn't a 100% assurance.)

    A sysread is a very long op, and you just instructed it NOT to exit when it receives a signal, but to restart, instead. Since it restarts (and doesn't return, yet), Perl can not process the signal - since it is still inside the sysread perlop.