=encoding utf-8 =head1 NAME IO::SigGuard - SA_RESTART in pure Perl =head1 SYNOPSIS IO::SigGuard::sysread( $fh, $buf, $size ); IO::SigGuard::sysread( $fh, $buf, $size, $offset ); IO::SigGuard::syswrite( $fh, $buf ); IO::SigGuard::syswrite( $fh, $buf, $len ); IO::SigGuard::syswrite( $fh, $buf, $len, $offset ); IO::SigGuard::select( $read, $write, $exc, $timeout ); =head1 DESCRIPTION C<perldoc perlipc> describes how Perl versions from 5.8.0 onward disable the OS’s SA_RESTART flag when installing Perl signal handlers. This module imitates that pattern in pure Perl: it does an automatic restart when a signal interrupts an operation so you can avoid the generally-useless EINTR error when using C<sysread()>, C<syswrite()>, and C<select()>. For this to work, whatever signal handler you implement will need to break out of this module, probably via either C<die()> or C<exit()>. =head1 ABOUT C<sysread()> and C<syswrite()> Other than that you’ll never see EINTR and that there are no function prototypes used (i.e., you need parentheses on all invocations), C<sysread()> and C<syswrite()> work exactly the same as Perl’s equivalent built-ins. =head1 ABOUT C<select()> To handle EINTR, C<IO::SigGuard::select()> has to subtract the elapsed time from the given timeout then repeat the internal C<select()>. Because the C<select()> built-in’s C<$timeleft> return is not reliable across all platforms, we have to compute the elapsed time ourselves. By default the only means of doing this is the C<time()> built-in, which can only measure individual seconds. This works, but there are two ways to make it more accurate: =over =item * Have L<Time::HiRes> loaded, and C<IO::SigGuard::select()> will use that module rather than the C<time()> built-in. =item * Set C<$IO::SigGuard::TIME_CR> to a compatible code reference. This is useful, e.g., if you have your own logic to do the equivalent of L<Time::HiRes>—for example, in Linux you may prefer to call the C<gettimeofday> system call directly from Perl to avoid L<Time::HiRes>’s XS overhead. =back In scalar contact, C<IO::SigGuard::select()> is a drop-in replacement for Perl’s 4-argument built-in. In list context, there may be discrepancies re the C<$timeleft> value that Perl returns from a call to C<select>. As per Perl’s documentation this value is generally not reliable anyway, though, so that shouldn’t be a big deal. In fact, on systems like MacOS where the built-in’s C<$timeleft> is completely useless, IO::SigGuard’s return is actually B<better> since it does provide at least a rough estimate of how much of the given timeout value is left. See C<perlport> for portability notes for C<select>. =head1 TODO This pattern could probably be extended to C<send>, C<recv>, C<flock>, and other system calls that can receive EINTR. If there’s a desire for that I’ll consider adding it. =head1 REPOSITORY L<https://github.com/FGasper/p5-IO-SigGuard> =head1 AUTHOR Felipe Gasper (FELIPE) … with special thanks to Mario Roy (MARIOROY) for extra testing and a few fixes/improvements. =head1 COPYRIGHT Copyright 2017 by L<Gasper Software Consulting|http://gaspersoftware.com> =head1 LICENSE This distribution is released under the same license as Perl.