]> git.proxmox.com Git - pve-client.git/blobdiff - PVE/APIClient/Commands/lxc.pm
lxc enter: set STDOUT to non-blocking mode
[pve-client.git] / PVE / APIClient / Commands / lxc.pm
index 979b580b0e2f363fe46522effa3d41bca6b02a60..c60017b551ebd750236568807d4b62d21e4c7024 100644 (file)
@@ -202,7 +202,9 @@ __PACKAGE__->register_method ({
 
        my $wb_socket_read_available_bytes = sub {
            my $nr = $web_socket->sysread($wsbuf, $max_payload_size, length($wsbuf));
-           die "web socket read error - $!\n" if $nr < 0;
+           if (!defined($nr) && !($! == EINTR || $! == EAGAIN)) {
+               die "web socket read error - $!\n";
+           }
            return $nr;
        };
 
@@ -258,12 +260,13 @@ __PACKAGE__->register_method ({
 
            # And set it to non-blocking so we can every char with IO::Select.
            STDIN->blocking(0);
-           $web_socket->blocking(1);
+           STDOUT->blocking(0);
+           $web_socket->blocking(0);
            $read_select->add($web_socket);
-           my $input_fh = fileno(STDIN);
+           my $input_fh = \*STDIN;
            $read_select->add($input_fh);
 
-           my $output_fh = fileno(STDOUT);
+           my $output_fh = \*STDOUT;
 
            my $ctrl_a_pressed_before = 0;
 
@@ -281,6 +284,8 @@ __PACKAGE__->register_method ({
                $winch_received = 0;
            };
 
+           my $max_buffer_len = 256*1024;
+
            my $drain_buffer = sub {
                my ($fh, $buffer_ref) = @_;
 
@@ -292,7 +297,8 @@ __PACKAGE__->register_method ({
                }
                return $nr if !$nr;
                substr($$buffer_ref, 0, $nr, '');
-               $write_select->remove($fh) if !length($$buffer_ref);
+               $len = length($$buffer_ref);
+               $write_select->remove($fh) if !$len;
            };
 
            while (1) {
@@ -301,7 +307,8 @@ __PACKAGE__->register_method ({
 
                    foreach my $fh (@$writable) {
                        if ($fh == $output_fh) {
-                           $drain_buffer->(\*STDOUT, \$output_buffer);
+                           $drain_buffer->($output_fh, \$output_buffer);
+                           $read_select->add($web_socket) if length($output_buffer) <= $max_buffer_len;
                        } elsif ($fh == $web_socket) {
                            $drain_buffer->($web_socket, \$websock_buffer);
                        }
@@ -314,14 +321,17 @@ __PACKAGE__->register_method ({
 
                            my $nr = $wb_socket_read_available_bytes->();
                            if (!defined($nr)) {
-                               die "web socket read error $!\n";
+                               # wait
                            } elsif ($nr == 0) {
                                return; # EOF
                            } else {
                                my ($payload, $req_close) = $parse_web_socket_frame->(\$wsbuf);
-                               if ($payload) {
+                               if (defined($payload) && length($payload)) {
                                    $output_buffer .= $payload;
                                    $write_select->add($output_fh);
+                                   if (length($output_buffer) > $max_buffer_len) {
+                                       $read_select->remove($web_socket);
+                                   }
                                }
                                return if $req_close;
                            }
@@ -329,7 +339,7 @@ __PACKAGE__->register_method ({
                        } elsif ($fh == $input_fh) {
                            # Read from STDIN
 
-                           my $nr = read(\*STDIN, my $buff, 4096);
+                           my $nr = sysread($input_fh, my $buff, 4096);
                            return if !$nr; # EOF or error
 
                            my $char = ord($buff);