Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Perl has three select() functions , with widely differing purposes. One form takes 4 four arguments , and is a wrapper around the POSIX select(3) call. A second form takes zero arguments and returns the currently selected filehandle. This is file handle: the handle of the output stream used by print; it normally defaults to standard output. The third form takes one argument: , a filehandlefile handle, and makes it the currently selected filehandlefile handle. That is, this form of select() changes the file that is used by all print statements (unless they each specify their own filehandlefile handle).

Modifying the filehandle file handle used by print is counterintuitive , as because subsequent print statements will no longer print to standared standard output. Furthermore, the globally selected filehandle file handle is not garbage-collected, and ; it remains open even if the filehandle itself file handle goes out of scope. Therefore, do not modify the selected filehandle file handle with select().

Noncompliant Code Example

...

Code Block
bgColor#ffcccc
langperl

sub output_log {
  my $action = shift;
  open( my $log, ">>", "log.txt");
  select( $log);
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  $year += 1900;
  $mon += 1;
  print "$year-$mon-$mday $hour:$min:$sec: $action\n";
}

# ...

print "Hello!\n";
output_log("Greeted user");
print "How are you?\n";

Unfortunately, the select() method causes the last print statement to print "How are you?" not to standard output , but to the log file.

Compliant Solution

This compliant solution avoids select() and directs the print() statement to use the log filehandle file handle for output.

Code Block
bgColor#ccccff
langperl

sub output_log {
  my $action = shift;
  open( my $log, ">>", "log.txt");
  ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  $year += 1900;
  $mon += 1;
  print $log "$year-$mon-$mday $hour:$min:$sec: $action\n";
}

Noncompliant Code Example (

...

Autoflush)

This noncompliant code example uses the 1one-argument select() function temporarily to modify the autoflush property associated with the file. The 1one-argument select() returns the old filehandle file handle (normally standard output). After the $log filehandle file handle is selected, the modification of $| instructs Perl to autoflush everything sent to the $log filehandle file handle. That is, every output to the $log filehandle file handle is flushed immediately. After the modification, select() is called again to restore the original selected filehandlefile handle.

Code Block
bgColor#ffcccc
langperl

select(( select($log), $| = 1)[0]);

...

Code Block
bgColor#ccccff
langperl

use IO::Handle;
# ...
$log->autoflush();

...

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

EXP37-PL

medium Medium

unlikely Unlikely

medium Medium

P14 P4

L3

Automated Detection

Tool

Diagnostic

Perl::Critic

InputOutput::ProhibitOneArgSelect

Bibliography

...

...

 

...

Image Added Image Added Image Added/]. [ProhibitOneArgSelect|http://search.cpan.org/dist/Perl-Critic/lib/Perl/Critic/Policy/InputOutput/ProhibitOneArgSelect.pm]. \[[Conway 2005|AA. Bibliography#Conway 2005]\], pg 224 \[[Wall 2011|AA. Bibliography#Manpages]\] [perlfunc|http://perldoc.perl.org/perlfunc.html]EXP11-C. Do not apply operators expecting one type to data of an incompatible type      03. Expressions (EXP)      EXP13-C. Treat relational and equality operators as if they were nonassociative