From 05185117208787ae086ff32f7f187d35182a7f94 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 24 Feb 2012 20:21:49 -0600 Subject: initial implementation --- lib/Select/Retry.pm | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/lib/Select/Retry.pm b/lib/Select/Retry.pm index e69de29..11a79e4 100644 --- a/lib/Select/Retry.pm +++ b/lib/Select/Retry.pm @@ -0,0 +1,52 @@ +package Select::Retry; +use strict; +use warnings; + +use Sub::Exporter -setup => { + exports => [ 'retry_select' ], + groups => { default => [ 'retry_select' ] }, +}; + +sub retry_select { + my ($mode, $timeout, @handles) = @_; + + my $got_winch; + my $old_winch = $SIG{WINCH}; + local $SIG{WINCH} = sub { + $got_winch = 1; + $old_winch->() if ref($old_winch) && ref($old_winch) eq 'CODE'; + }; + + my ($out, $eout); + my ($in, $ein) = (_build_select_vec(@handles)) x 2; + my $res; + if ($mode eq 'r') { + $res = select($out = $in, undef, $eout = $ein, $timeout); + } + else { + $res = select(undef, $out = $in, $eout = $ein, $timeout); + } + my $again = $!{EAGAIN} || $!{EINTR}; + + if (($res == -1 && $again) || $got_winch) { + return retry_select(@_); + } + elsif ($res == -1) { + Carp::croak("select failed: $!"); + } + + return ($out, $eout); +} + +sub _build_select_vec { + my @handles = @_; + + my $vec = ''; + for my $handle (@handles) { + vec($vec, fileno($handle), 1) = 1; + } + + return $vec; +} + +1; -- cgit v1.2.3