Bug 859257

Summary: Defered signal handling doesn't work correctly when interrupted by another signal
Product: Red Hat Enterprise Linux 6 Reporter: Justin Washington <jwjw9922>
Component: perlAssignee: perl-maint-list
Status: CLOSED NOTABUG QA Contact: BaseOS QE - Apps <qe-baseos-apps>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 6.3CC: ppisar, psabata
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-09-24 10:49:34 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Justin Washington 2012-09-20 23:05:21 UTC
Description of problem:

Perl 5.7.3 and later use Deferred Signals. But it doesn't work correctly if another signal arrives when the signal handler is running.


Version-Release number of selected component (if applicable):

- Perl 5.10.1 on RHEL 6.3
- Perl 5.8.8 on RHEL 5.8

How reproducible:

Yes

Steps to Reproduce:

Run this testing script:

#!/usr/bin/perl

our $i = 0;

$SIG{CHLD} = \&sighandler;
kill CHLD => $$;

exit;

sub sighandler {
    exit if $i == 6;
    print ++$i, ": processing", "\n";
    kill CHLD => $$;
    print $i, ": done", "\n";
}

  
Actual results:

On RHEL 6.3 and RHEL 5.8, it outputs:

1: processing
1: done
2: processing
2: done

And then script exists. 

Expected results:

On Ubuntu 12.04 x86_64 with Perl 5.14.2, it runs correctly and outputs:

1: processing
1: done
2: processing
2: done
3: processing
3: done
4: processing
4: done
5: processing
5: done
6: processing
6: done

Additional info:

Probably Perl 5.14 fixed this bug. It would be great if this fix can be back ported to RHEL 5.8 and RHEL 6.3

Comment 2 Justin Washington 2012-09-20 23:39:10 UTC
Here are 3 some other tests:


1). Script t1.pl:

#!/usr/bin/perl

use POSIX;

our $i = 0;

if (1) {
    my $sigaction = POSIX::SigAction->new(\&sighandler, POSIX::SigSet->new());
    $sigaction->safe(1);
    POSIX::sigaction(&POSIX::SIGCHLD, $sigaction);
}

kill CHLD => $$;

exit;

sub sighandler {
    exit if $i == 6;
    print ++$i, ": processing", "\n";
    kill CHLD => $$;
    print $i, ": done", "\n";
}


Output:


1: processing
1: done
2: processing
2: done

2). Script t2.pl


#!/usr/bin/perl

use POSIX;

our $i = 0;

if (1) {
    my $sigaction = POSIX::SigAction->new(\&sighandler, POSIX::SigSet->new());
    #$sigaction->safe(1);
    POSIX::sigaction(&POSIX::SIGCHLD, $sigaction);
}

kill CHLD => $$;

exit;

sub sighandler {
    exit if $i == 6;
    print ++$i, ": processing", "\n";
    kill CHLD => $$;
    print $i, ": done", "\n";
}

Output:


1: processing
1: done
2: processing
2: done
3: processing
3: done
4: processing
4: done
5: processing
5: done
6: processing
6: done


3). Script t3.pl:


#!/usr/bin/perl

use POSIX;

our $i = 0;

my $sigaction = POSIX::SigAction->new(\&sighandler, POSIX::SigSet->new());
$sigaction->safe(1);
POSIX::sigaction(&POSIX::SIGCHLD, $sigaction);

kill CHLD => $$;

exit;

sub sighandler {
    exit if $i == 6;
    print ++$i, ": processing", "\n";
    kill CHLD => $$;
    print $i, ": done", "\n";
}


Output:


1: processing
1: done
2: processing
2: done
3: processing
3: done
4: processing
4: done
5: processing
5: done
6: processing
6: done


The output of script t1.pl is not correct.

Comment 3 Petr Pisar 2012-09-24 09:35:05 UTC
Where you get confidence that all 6 signals get processed or even emitted before the code reaches exit call in the main program?

Comment 4 Petr Pisar 2012-09-24 10:49:34 UTC
Adding 

while ($i < 6) {sleep 1;}

just before `exit' in the t1.pl as well as in the code from comment #1 does fix your problem. I'm really keen to say your code is missing a synchronization.