Subject: | Use of non-lexical $_ can break uplevel code |
Linux::Proc::Mounts uses a while loop that assigns each value from readline to $_, instead of using a discrete lexical variable. Consider the attached program. In my case, it prints:
Use of uninitialized value in list assignment at test line 12.
$VAR1 = {
'/var/tmp' => '/dev/sda2',
'/home' => '/dev/root',
'' => '/dev/root'
};
However, if $BUG is set to 0, it works as expected:
$VAR1 = {
'/var/tmp' => '/dev/sda2',
'/' => '/dev/root',
'/home' => '/dev/root'
};
I recommend that the code be changed to `while my $line (<$fh>)` or such, so as to protect against mid-air collisions of this kind.
Subject: | linux-proc-mounts-bug.pl |
#!/usr/bin/perl
use feature 'state';
use warnings;
use Data::Dumper;
use Linux::Proc::Mounts;
use Path::Tiny;
my $BUG = 0;
my @paths = ('/', '/home', '/var/tmp');
my %dev_by = map { $_ => blkdev_by_path($_) } @paths;
print Dumper \%dev_by;
sub blkdev_by_path {
my $path = shift;
state $dev_by;
if (! defined $dev_by) {
if ($BUG) {
%$dev_by = map { $_->file => $_->spec } @{ Linux::Proc::Mounts->read };
} else {
%$dev_by = map { $_->file => $_->spec } @{ read_mounts() };
}
}
$path = path($path);
while (1) {
if (exists $dev_by->{$path}) {
return $dev_by->{$path};
}
if ($path->is_rootdir) {
last;
}
$path = $path->parent;
}
return undef;
}
sub read_mounts {
local $_;
return Linux::Proc::Mounts->read;
}