Thursday, August 19, 2010

Resolving Perl CGI buffering issue

It is typical issue in Perl CGI that output doesn’t appear immediately until the whole script ends.  It is not desired for lengthy operations, because users want to see helpful message in advance rather than a blank page.
It is because that buffering of STDOUT is enabled ($|=0) by default, The following are two solutions to resolve the issue.

Requirements:

You need Apache2 Perl mod_perl2 and Perl module: CGI.pm.
Following is the environment where my scripts were tested ( However the versions  are NOT  minimum requirements)

Apache/2.2.11 (Ubuntu)
mod_perl/2.0.4
Perl/v5.10.0
libcgi-pm-perl 3.42-1 
Apache Server configuration
The handler has to be perl-script, handler cgi-script won’t work.
<Directory /var/www/scripts>
SetHandler perl-script
PerlResponseHandler ModPerl::Registry
PerlOptions +ParseHeaders
Options +ExecCGI
</Directory> 

Solution #1

Enable buffering and use mod_perl API ($r is mod_perl request object) to print.

#!/usr/bin/perl -w
use CGI qw(:standard);
$|=1;
my $r = shift;
print header('text/html');
print start_html;
$r->print ("Processing ... <br>");
foreach $i (1..2) {
sleep 2;
$r->print ("Item .. $i <br>");
}
$r->print ("DONE <br>");
print end_html; 


Solution #2

Disable buffering and use mod_perl API rflush function to flush buffer as needed.
“print br” is CGI.pm function to print a new line.
“$r->rflush” is mod_perl function to flush any buffered data to the client


#!/usr/bin/perl -w
use CGI qw(:standard);
my $r = shift;
print header('text/html');
print start_html;
print br ("Processing ... ");
$r->rflush; 
foreach $i (1..2) {
sleep 2;
print br  ("Item .. $i ");
$r->rflush;
}
print br ("DONE");
print end_html;

No comments:

Post a Comment