Remote-Perl

 view release on metacpan or  search on metacpan

lib/Remote/Perl/Client.pm  view on Meta::CPAN

use strict;
use warnings;
# NOTE: this file runs on the remote side and must stay compatible with Perl 5.10+.
package Remote::Perl::Client;

# Remote bootstrap client.  Sent verbatim by Bootstrap.pm and eval'd on the
# remote side.  Only uses Perl core modules.
#
# Architecture: one persistent relay process, plus one executor per RUN.
#   Client (relay)  -- owns the protocol pipe; runs the select loop permanently.
#   Executor        -- runs the user script with real STDIN/STDOUT/STDERR pipes.
#
# This split means the protocol loop is never blocked by script I/O, enabling
# real-time stdout/stderr streaming and correct signal forwarding.

use Fcntl  qw(F_SETFD FD_CLOEXEC O_RDWR);
use Socket qw(AF_UNIX SOCK_STREAM);
use POSIX  qw(WNOHANG);

# -- Save real pipe handles before any redirection -----------------------------
open(my $PIN,  '<&', \*STDIN)  or die "dup STDIN: $!\n";
open(my $POUT, '>&', \*STDOUT) or die "dup STDOUT: $!\n";
binmode($PIN); binmode($POUT);
{ my $old = select $POUT; $| = 1; select $old }
$SIG{PIPE} = 'IGNORE';

syswrite($POUT, "REMOTEPERL1\n");

# -- Constants -----------------------------------------------------------------
use constant {
    HDR             => 6,
    PROTO_VER       => 2,
    MSG_HELLO       => 0x00,   MSG_READY       => 0x01,
    MSG_RUN         => 0x10,
    MSG_DATA        => 0x20,   MSG_EOF         => 0x21,
    MSG_CREDIT      => 0x30,
    MSG_MOD_REQ     => 0x40,   MSG_MOD_MISSING => 0x41,
    MSG_RETURN      => 0x50,
    MSG_SIGNAL      => 0x60,   MSG_SIGNAL_ACK  => 0x61,
    MSG_ERROR       => 0xE0,   MSG_BYE         => 0xF0,
    S_CTRL          => 0,      S_STDIN         => 1,
    S_STDOUT        => 2,      S_STDERR        => 3,
};

# -- State ---------------------------------------------------------------------
my $pbuf        = '';
my %sc          = ();   # send credits: stream_id => bytes remaining
my $window      = 65536;
my $done        = 0;
my $next_stream = 4;

# -- Wire I/O ------------------------------------------------------------------

# Write bytes to the protocol pipe.
sub _write {
    my ($bytes) = @_;
    my ($total, $off) = (length($bytes), 0);
    while ($off < $total) {
        my $n = syswrite($POUT, $bytes, $total - $off, $off);
        die "syswrite: $!\n" unless defined $n;
        $off += $n;
    }
}

sub _send {
    my ($type, $stream, $body) = @_;
    $body //= '';
    _write(pack('CCN', $type, $stream, length($body)) . $body);
}

# Write all bytes to an arbitrary filehandle (pipes, sockets).
sub _write_fh {
    my ($fh, $bytes) = @_;



( run in 3.096 seconds using v1.01-cache-2.11-cpan-71847e10f99 )