Skip to content
This repository was archived by the owner on Mar 15, 2024. It is now read-only.
This repository was archived by the owner on Mar 15, 2024. It is now read-only.

Stucked while trying to match login prompt #16

@shunghsiyu

Description

@shunghsiyu

When there is a newline before the login prompt (i.e. "\nlocalhost login: "), runltp-ng will fail to recognize the prompt, thus not proceed with entering the username; this is because it get stucked polling forever at $poll->poll($timeout) (since timeout is not passed to backend::start).

Below is a script that mimics this issue.
wait_regexp and try_readline is copied directly from the backend module, with minor modification to avoid actually reading file descriptor (by mocking sysread).

#!/usr/bin/env perl
use strict;
use warnings;
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);

use lib './';
use backend;
use log;

my $mock_sysread_cnt = 0;
my $out_fd_buf = "\nlocalhost login: ";

sub try_readline
{
	my ($self, $timeout) = @_;

	return backend::split_line($self) if backend::has_newline($self);

	#my $poll = IO::Poll->new();
	#$poll->mask($self->{'out_fd'} => POLLIN);

	while (1) {
		#if ($poll->poll($timeout) == 0) {
		#	msg("$self->{'name'}: Timeouted!\n");
		#	return undef;
		#}
		if (!defined($timeout) && $out_fd_buf eq '') {
			die("Will get stucked here polling forever\n");
		}

		my $buf = '';
		#my $ret = sysread($self->{'out_fd'}, $buf, 128);
		# --- Mocking sysread ---
		my $ret = 0;
		if ($mock_sysread_cnt == 0) {
			$ret = length($out_fd_buf);
			$buf = $out_fd_buf;
			$out_fd_buf = '';
			$mock_sysread_cnt += 1;
		} else {
			die("Will not reach here");
		}
		# -----------------------
		
		#print("R: '$buf'\n");
		$self->{'buf'} .= $buf;
		last if !defined($ret) && $!{EAGAIN};
		last if $ret > 0;
		return undef if !defined($ret);
		return undef if $ret == 0;
	}

	return backend::split_line($self) if backend::has_newline($self);

	return $self->{'buf'};
}

sub wait_regexp
{
	my ($self, $regexp, $newline, $timeout) = @_;
	my $out_fd = $self->{'out_fd'};
	my @log;
	my $line;

	msg("Waiting for regexp '$regexp'\n");

	my $start_time = backend::clock_gettime(CLOCK_MONOTONIC);

	while (1) {
		$line = try_readline($self, $timeout);

		if (!defined($line)) {
			msg("$self->{'name'}: died!\n");
			return @log;
		}

		if ($line =~ /\n/) {
			msg("$self->{'name'}: $line");
			my $l = $line;
			# Strip CR LF
			$l =~ s/(\x0d|\x0a)//g;
			# Strip escape sequencies
			$l =~ s/\x1b\[[0-9;]*[a-zA-Z]//g;
			push(@log, $l);
			my $fh = $self->{'raw_logfile'};
			print($fh "$l\n") if defined($fh);
		}
		#print("N: $self->{'name'}: $line\n") if $verbose;

		if (defined($timeout) and clock_gettime(CLOCK_MONOTONIC) - $start_time > $timeout) {
			msg("$self->{'name'}: timeouted!\n");
			return @log;
		}

		next if (defined($newline) && $newline && $line !~ /\n/);

		last if ($line =~ m/$regexp/);
	}

	return @log;
}

log::set_verbosity(1);

my %instance;
$instance{'name'} = 'qemu';
$instance{'buf'} = '';
wait_regexp(\%instance, qr/login:/);

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions