It's a common enough situation. I think a lot of us figured it out in just this way too.
perlman:perlsub, perlman:perlsyn and perlman:perlvar all have
some comments about this, but it can be hard to get the picture from
those without someone (or some bug) pointing it out.
perlman:perlvar states that $_ is assigned to in your while
case, but doesn't make it clear that $_ isn't localized by while
as a foreach would.
Either localize $_ yourself, or switch to another while
style for any loop that calls subroutines:
while (my $line = <FILE>) {