13 Jun 2020 11:05:00 UTC
- Distribution: IO-SigGuard
- Module version: 0.15
- Source (raw)
- Browse (raw)
- How to Contribute
- Testers (1530 / 159 / 0)
- KwaliteeBus factor: 1
- % Coverage
- License: perl_5
- Activity24 month
- Download (14.63KB)
- MetaCPAN Explorer
- Subscribe to distribution
- This version
- Latest versionFELIPE Felipe Gasperand 1 contributors
- Felipe Gasper
- ABOUT sysread() and syswrite()
- ABOUT select()
IO::SigGuard - SA_RESTART in pure Perl
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::send( $fh, $msg, $flags ); IO::SigGuard::send( $fh, $msg, $flags, $to ); IO::SigGuard::select( $read, $write, $exc, $timeout );
perldoc perlipcdescribes 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
For this to work, whatever signal handler you implement will need to break out of this module, probably via either
Other than that you’ll never see EINTR and that there are no function prototypes used (i.e., you need parentheses on all invocations),
syswrite()work exactly the same as Perl’s equivalent built-ins.
As of version 0.13 this module’s functions lazy-load by default. To have functionality loaded at compile time give the function name to the import logic, e.g.:
use IO::SigGuard qw(send recv);
To handle EINTR,
IO::SigGuard::select()has to subtract the elapsed time from the given timeout then repeat the internal
select(). Because the
$timeleftreturn is not reliable across all platforms, we have to compute the elapsed time ourselves. By default the only means of doing this is the
time()built-in, which can only measure individual seconds.
This works, but there are two ways to make it more accurate:
Have Time::HiRes loaded, and
IO::SigGuard::select()will use that module rather than the
$IO::SigGuard::TIME_CRto a compatible code reference. This is useful, e.g., if you have your own logic to do the equivalent of Time::HiRes—for example, in Linux you may prefer to call the
gettimeofdaysystem call directly from Perl to avoid Time::HiRes’s XS overhead.
In scalar contact,
IO::SigGuard::select()is a drop-in replacement for Perl’s 4-argument built-in.
In list context, there may be discrepancies re the
$timeleftvalue that Perl returns from a call to
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
$timeleftis completely useless, IO::SigGuard’s return is actually better since it does provide at least a rough estimate of how much of the given timeout value is left.
perlportfor portability notes for
This pattern could probably be extended to other system calls that can receive EINTR. I’ll consider adding new calls as requested.
Felipe Gasper (FELIPE)
… with special thanks to Mario Roy (MARIOROY) for extra testing and a few fixes/improvements.
Copyright 2017 by Gasper Software Consulting
This distribution is released under the same license as Perl.