arayq2
arayq2

Reputation: 2554

<> hangs on STDIN after reading non-empty @ARGV

The code below is the skeleton of a perl program to process some files with structured text. The program works as expected if the input is provided via STDIN:

./process_files.pl < some_file

But it hangs if the file to be processed is a command line argument:

./process_files.pl some_file

Running this under strace showed that after reading the file, the program is stuck on read(0, ...). And sure enough, typing Ctrl-D at the terminal unsticks the program and it then runs to completion.

Why is perl waiting on STDIN after reading from a non-empty @ARGV?

The perl code:

#!/usr/bin/perl

sub meta
{
    while ( <> )
    {
        return if m!</META>!;
        # process metadata line
    }
}

sub data
{
    while ( <> )
    {
        return if m!</DATA>!;
        # process data line
    }
}

while ( <> )
{
    meta if m!<META>!;
    data if m!<DATA>!;
}

# post processing here

exit 0;

ADDENDUM: the lines of the text file being processed have this pattern:

lines (ignored)
<META>
meta data lines (processed)
</META>
lines (ignored)
<DATA>
data lines (processed)
</DATA>
optional lines (ignored)

Upvotes: 0

Views: 330

Answers (1)

ikegami
ikegami

Reputation: 386551

The problem is that you kept read from ARGV after it returned EOF.

Reading from ARGV removes the entries from @ARGV as it opens them, so @ARGV was empty the second go around, causing the read to read from STDIN.

Your program boils down to the following:

print "\@ARGV: @ARGV\n";     # Outputs: @ARGV: file.txt
while (<>) { }               # Reads from file.txt.
print "\@ARGV: @ARGV\n";     # Outputs: @ARGV:
while (<>) { }               # Reads from STDIN.

By the way, you should never expect a file handle that returned EOF to keep returning EOF. This is not always the case. For example, it's not the case for handles to terminals on POSIX systems.

Upvotes: 4

Related Questions