Commit 5f5e5d1b authored by Guillaume Huard's avatar Guillaume Huard
Browse files

Sets and select factorization

parent da588093
......@@ -83,6 +83,73 @@ sub get_value($$$) {
}
}
sub sets_create() {
my $sets = {};
$sets->{left} = 0;
$sets->{avail} = {};
$sets->{read} = $sets->{write} = $sets->{except} = '';
return $sets;
}
sub sets_empty($) {
my $sets = shift;
return $sets->{left} == 0;
}
sub sets_add($$$) {
my $sets = shift;
my $set = shift;
my $stream = shift;
$sets->{$stream} = $set;
my $fd = fileno($stream);
vec($sets->{$set}, $fd, 1) = 1;
vec($sets->{except}, $fd, 1) = 1;
$sets->{left}++;
}
sub sets_select($) {
my $sets = shift;
my $avail = $sets->{avail};
my $nfound = select($avail->{read} = $sets->{read}, $avail->{write} = $sets->{write},
$avail->{except} = $sets->{except}, undef);
}
sub sets_avail($$) {
my $sets = shift;
my $stream = shift;
my $set = $sets->{$stream};
my $fd = fileno($stream);
# if (vec($sets->{avail}->{except}, $fd, 1)) {
# debug("Unexpected exceptionnal condition on command fd $fd with $set access\n");
# }
return vec($sets->{avail}->{$set}, $fd, 1);
}
sub sets_access($$$$$) {
my $sets = shift;
my $stream = shift;
my $buffer = shift;
my $length = shift;
my $offset = shift;
my $set = $sets->{$stream};
if ($set eq 'read') {
return sysread($stream, $$buffer, $length, $offset);
} else {
return syswrite($stream, $$buffer, $length, $offset);
}
}
sub sets_remove($$) {
my $sets = shift;
my $stream = shift;
my $set = $sets->{$stream};
my $fd = fileno($stream);
vec($sets->{$set}, $fd, 1) = 0;
$sets->{left}--;
close($stream);
}
# Runs a command associated to a test with a given input, returns a hash that holds the content of standard output and error as well as exit code
# Looks at outputs_limit, timeout, debug, args and input in the test to find out how to run it (but they are not necessarily expected to exist)
sub run_command($$$$) {
......@@ -143,42 +210,25 @@ sub run_command($$$$) {
debug("\n");
# we use select to perform I/Os with the child (still in order to avoid deadlocks)
my $sets = {};
my $left = 3;
$sets->{read} = $sets->{write} = $sets->{except} = '';
vec($sets->{write}, fileno($child->{input}), 1) = 1;
vec($sets->{read}, fileno($child->{output}), 1) = 1;
vec($sets->{read}, fileno($child->{error}), 1) = 1;
$sets->{except} = $sets->{read} | $sets->{write};
while ($left) {
my $avail = {};
my $nfound = select($avail->{read} = $sets->{read}, $avail->{write} = $sets->{write}, $avail->{except} = $sets->{except}, undef);
my $sets = sets_create();
sets_add($sets, 'write', $child->{input});
sets_add($sets, 'read', $child->{output});
sets_add($sets, 'read', $child->{error});
while (!sets_empty($sets)) {
sets_select($sets);
for my $part (keys(%$child)) {
my $fd = fileno($child->{$part});
my $set;
if ($part eq 'input') {
$set = 'write';
} else {
$set = 'read';
}
if (vec($avail->{$set}, $fd, 1) == 1) {
if (sets_avail($sets, $child->{$part})) {
my $number;
my $size = $remaining->{$part};
$size = 1024 if $size == -1;
if ($part eq 'input') {
$number = syswrite($child->{$part}, $data->{$part}, $size, $done->{$part});
} else {
$number = sysread($child->{$part}, $data->{$part}, $size, $done->{$part});
}
$number = sets_access($sets, $child->{$part}, \$data->{$part}, $size, $done->{$part});
if (!defined($number)) {
if ($!{EINTR} || $!{EAGAIN} || $!{EWOULDBLOCK}) {
debug("$set access to command temporarily failed for reason $!\n");
debug("Access to command temporarily failed for reason $!\n");
} else {
debug("Error $! during $set access to command $part through file descriptor $fd\n");
vec($sets->{$set}, $fd, 1) = 0;
$left--;
close($child->{$part});
debug("Error $! during access to command $part\n");
sets_remove($sets, $child->{$part});
delete($child->{$part});
}
} else {
......@@ -187,10 +237,7 @@ sub run_command($$$$) {
$done->{$part} += $number;
}
if (!$number || !$remaining->{$part}) {
vec($sets->{$set}, $fd, 1) = 0;
$left--;
# debug("Closing $fd in set $set for part $part\n");
close($child->{$part});
sets_remove($sets, $child->{$part});
delete($child->{$part});
}
if (!$remaining->{$part}) {
......@@ -198,10 +245,6 @@ sub run_command($$$$) {
}
}
}
# Actually in exceptional condition on OSX, better left ignored
# if (vec($avail->{except}, $fd, 1) == 1) {
# debug("Unexpected exceptionnal condition on command file descriptor for $part\n");
# }
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment