diff options
author | David Golden <xdg@xdg.me> | 2015-12-25 20:44:44 -0500 |
---|---|---|
committer | David Golden <xdg@xdg.me> | 2015-12-25 22:08:23 -0500 |
commit | 852982580b27fdc9e90d03215913b6652dccdfa9 (patch) | |
tree | 6444354d19005487d15f6991a6fdd5a3325a9abb /lib | |
parent | e73fbd3e36de3699c5caa22b20b65d1c553bfa6e (diff) | |
download | perl-libnet-852982580b27fdc9e90d03215913b6652dccdfa9.tar.gz |
Refactor syswrite with timeout
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Net/Cmd.pm | 109 |
1 files changed, 57 insertions, 52 deletions
diff --git a/lib/Net/Cmd.pm b/lib/Net/Cmd.pm index e9d0d25..bd4857b 100644 --- a/lib/Net/Cmd.pm +++ b/lib/Net/Cmd.pm @@ -18,6 +18,7 @@ use warnings; use Carp; use Exporter; use Symbol 'gensym'; +use Errno 'EINTR'; BEGIN { if ($^O eq 'os390') { @@ -189,7 +190,57 @@ sub set_status { 1; } +sub _syswrite_with_timeout { + my $cmd = shift; + my $line = shift; + + my $len = length($line); + my $offset = 0; + my $win = ""; + vec($win, fileno($cmd), 1) = 1; + my $timeout = $cmd->timeout || undef; + my $initial = time; + my $pending = $timeout; + + local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS'; + + while ($len) { + my $wout; + my $nfound = select(undef, $wout = $win, undef, $pending); + if ((defined $nfound and $nfound > 0) or -f $cmd) # -f for testing on win32 + { + my $w = syswrite($cmd, $line, $len, $offset); + if (! defined($w) ) { + my $err = $!; + $cmd->close; + $cmd->_set_status_closed($err); + return; + } + $len -= $w; + $offset += $w; + } + elsif ($nfound == -1) { + if ( $! == EINTR ) { + if ( defined($timeout) ) { + redo if ($pending = $timeout - ( time - $initial ) ) > 0; + $cmd->_set_status_timeout; + return; + } + redo; + } + my $err = $!; + $cmd->close; + $cmd->_set_status_closed($err); + return; + } + else { + $cmd->_set_status_timeout; + return; + } + } + return 1; +} sub _set_status_timeout { my $cmd = shift; @@ -201,11 +252,12 @@ sub _set_status_timeout { sub _set_status_closed { my $cmd = shift; + my $err = shift; my $pkg = ref($cmd) || $cmd; $cmd->set_status($cmd->DEF_REPLY_CODE, "[$pkg] Connection closed"); carp(ref($cmd) . ": " . (caller(1))[3] - . "(): unexpected EOF on command channel: $!") if $cmd->debug; + . "(): unexpected EOF on command channel: $err") if $cmd->debug; } sub _is_closed { @@ -463,33 +515,8 @@ sub datasend { ${*$cmd}{'net_cmd_last_ch'} = substr($line, -1, 1); - my $len = length($line); - my $offset = 0; - my $win = ""; - vec($win, fileno($cmd), 1) = 1; - my $timeout = $cmd->timeout || undef; - - local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS'; - - while ($len) { - my $wout; - my $s = select(undef, $wout = $win, undef, $timeout); - if ((defined $s and $s > 0) or -f $cmd) # -f for testing on win32 - { - my $w = syswrite($cmd, $line, $len, $offset); - unless (defined($w) && $w == $len) { - $cmd->close; - $cmd->_set_status_closed; - return; - } - $len -= $w; - $offset += $w; - } - else { - $cmd->_set_status_timeout; - return; - } - } + $cmd->_syswrite_with_timeout($line) + or return; 1; } @@ -511,30 +538,8 @@ sub rawdatasend { print STDERR $b, join("\n$b", split(/\n/, $line)), "\n"; } - my $len = length($line); - my $offset = 0; - my $win = ""; - vec($win, fileno($cmd), 1) = 1; - my $timeout = $cmd->timeout || undef; - - local $SIG{PIPE} = 'IGNORE' unless $^O eq 'MacOS'; - while ($len) { - my $wout; - if (select(undef, $wout = $win, undef, $timeout) > 0) { - my $w = syswrite($cmd, $line, $len, $offset); - unless (defined($w) && $w == $len) { - $cmd->close; - $cmd->_set_status_closed; - return; - } - $len -= $w; - $offset += $w; - } - else { - $cmd->_set_status_timeout; - return; - } - } + $cmd->_syswrite_with_timeout($line) + or return; 1; } |