There's an issue with the subroutine originally posted.
The shift function expects an array as an argument. The implicit variable inside the foreach is a scalar.
This means that $fh remains uninitialized. The reason why it probably goes unnoticed is because (as eugene y points out) lexical filehandles close themselves when they go out of scope.
Incidentally, use warnings; will notify about such things.
A more idiomatic approach would be to use a while loop:
sub closef {
while ( my $fh = shift @_ ) {
close $fh;
}
}
For more compact notation, a for loop is the way to go:
sub closef { close for @_; }
The equivalent with a while loop is not so readable:
sub closef { close while $_ = shift }
Update
Michael Carman's comment below holds true here. The shift modifies the array being iterated over, which makes it an unsafe operation. This is, in fact, the problem.