mrakus has asked for the wisdom of the Perl Monks concerning the following question:

Hello. I'm using nginx + perl for creating FastCGI web site. But i found some bug. When i use FCGI::ProcManager with CGI::Fast script it's not work true.
apt-cache policy nginx libcgi-fast-perl libfcgi-perl libfcgi-procmanag +er-perl nginx: Installed: 0.6.34-2 Candidate: 0.6.34-2 Version table: *** 0.6.34-2 0 500 http://ftp.fi.debian.org unstable/main Packages 100 /var/lib/dpkg/status libcgi-fast-perl: Installed: 5.10.0-22 Candidate: 5.10.0-22 Version table: *** 5.10.0-22 0 500 http://ftp.fi.debian.org unstable/main Packages 100 /var/lib/dpkg/status libfcgi-perl: Installed: 0.67-3 Candidate: 0.67-3 Version table: *** 0.67-3 0 500 http://ftp.fi.debian.org unstable/main Packages 100 /var/lib/dpkg/status libfcgi-procmanager-perl: Installed: 0.18-2 Candidate: 0.18-2 Version table: *** 0.18-2 0 500 http://ftp.fi.debian.org unstable/main Packages 100 /var/lib/dpkg/status
In nginx /etc/nginx/sites-enabled/test.com
server { listen 127.0.0.1; server_name test.com; access_log /var/www/test.com/log/access_log; error_log /var/www/test.com/log/error_log; location ~* ^.+\.(html|htm|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar +|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|mov)$ { root /var/www/test.com/html; } location / { set $scriptname ""; if ($fastcgi_script_name = "/") { set $scriptname "main"; } if ($fastcgi_script_name ~ ^/(.*)/$) { set $scriptname $1; } gzip off; #gzip makes scripts feel slower since they have to c +omplete before getting gzipped fastcgi_pass 127.0.0.1:9090; fastcgi_param SCRIPT_FILENAME $scriptname; include /etc/nginx/fastcgi_params; } }
My website code (shorter):

#!/usr/bin/perl use strict; use FCGI::ProcManager; use CGI::Fast; use POSIX qw(setsid); my $PROCESSES = 1; my $SOCKET = "127.0.0.1:9090"; my $cgi; my $count = 0; # for debug !!! #&daemonize; #this keeps the program alive or something after exec'ing perl scripts BEGIN() { } END() { } *CORE::GLOBAL::exit = sub { die "fakeexit\nrc=".shift()."\n"; }; eval q{exit}; if ($@) { exit unless $@ =~ /^fakeexit/; }; &main; sub daemonize() { chdir '/' or die "Can't chdir to /: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; umask 0; } sub main { my $proc_manager = new FCGI::ProcManager({ n_processes => $PROCESS +ES}); my $socket = FCGI::OpenSocket($SOCKET, 100); my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $s +ocket); $proc_manager->pm_manage(); while($request->Accept() >= 0){ $proc_manager->pm_pre_dispatch(); $cgi = new CGI::Fast; #$cgi = new CGI; second example !!! &website(); $proc_manager->pm_post_dispatch(); } FCGI::CloseSocket($socket); } sub website() { my $title; my $description; my $keywords; my $script = $ENV{SCRIPT_FILENAME}; if($script eq 'main'){ $title = 'Main'; $description = ''; $keywords = ''; &action_main($title,$description,$keywords); } elsif($script eq 'order'){ $title = 'Order'; $description = ''; $keywords = ''; &action_order($title,$description,$keywords); } else{ $title = 'Page not found!'; $description = ''; $keywords = ''; &page_not_found($title,$description,$keywords); } } sub header { $count++; print <<"T"; Content-type: text/html\r\n\r <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ut +f-8"> <title>$_[0]</title> <meta name="Description" content="$_[1]"> <meta name="Keywords" content="$_[2]"> </head> <body>$count<br> <table cellspacing="5" cellpadding="5" border="0"> <tr> <td> WEB-SITE!!! </td> </tr> <tr> <td> <table cellspacing="5" cellpadding="5" border="0"> <tr> <td> <a href="/">Main</a> </td> <td> <a href="/order/">Order Online</a> </td> </tr> </table> </td> </tr> <tr> <td> T foreach (keys %ENV){ # this is for debug!!! print "$_: $ENV{$_}<br>"; } } sub end { print <<'T'; </td> </tr> </table> </body> </html> T } sub action_main { &header(@_); print <<'T'; <br>THIS IS MAIN PAGE TEXT T &end(); } sub action_order { &header(@_); my $need = ' <font color="blue">*</font>'; my $error = ' <font color="red">*</font>'; my $errorflag = 0; my $send = 0; $send = 1 if(defined($cgi->param('send'))); my %hash; foreach ( qw{mail firstname mobile} ){ $hash{$_}->{title} = ''; if($_ eq 'mobile' or $_ eq 'firstname'){ $hash{$_}->{title} = $need; if($send and !defined($cgi->param($_))){ $hash{$_}->{title} .= $error; $errorflag = 1; } } if($send){ $hash{$_}->{value} = $cgi->param($_); } else{ $hash{$_}->{value} = ''; } } print <<"T"; <form action="/order/" method="POST"> <table width=600 cellspacing=5 cellpadding=5 border=0> <tr> <td>$send Your e-mail $hash{mail}->{title}</td> <td><input type="text" name="mail" value="$hash{mail}->{value} +"></td> </tr> <tr> <td>Name $hash{firstname}->{title}</td> <td><input type="text" name="firstname" value="$hash{firstname +}->{value}"></td> </tr> <tr> <td>Phone $hash{mobile}->{title}</td> <td><input type="text" name="mobile" value="$hash{mobile}->{va +lue}"></td> </tr> <tr> <input type=hidden name="send" value="1"> <td colspan="2" align="center"><input type=reset value="Clear" +>&nbsp;<input type=submit value="Send!"></td> </tr> </table> </form> T &end(); } sub page_not_found { &header(@_); print <<'T'; Page not found!!! T &end(); }

I start scipt as ./script.pl its run ok.

Now i go to test.com in browser and click:
"Main" menu - it's ok, then
click "Order" - wrong! $ENV{SCRIPT_FILENAME} eq "main" why?

Then i comment line "$cgi = new CGI::Fast;" and uncomment "$cgi = new CGI;" in script.pl, restart it.

Go to test.com in browser and click:
"Main" menu - it's ok, then
click "Order" - it's ok and work perfect!

But CGI module not work with FastCGI and may to read POST parameters only ones :(

Do you have ideas? My /dev/hands are broken or bug in perl modules? :)

Replies are listed 'Best First'.
Re: FCGI::ProcManager or CGI::Fast have bug?
by mrakus (Initiate) on May 25, 2009 at 16:12 UTC
    Ohhh.. I'm sorry Monks... it was my broken /dev/hands :(

    My FastCGI architecture was wrong!

    This is true architecture:
    #!/usr/bin/perl BEGIN { $ENV{FCGI_SOCKET_PATH} = "127.0.0.1:9090"; $ENV{FCGI_LISTEN_QUEUE} = 5; } use CGI::Fast; use FCGI::ProcManager; my $proc_manager = FCGI::ProcManager->new({ n_processes => 1 }); $proc_manager->pm_manage(); my $count = 0; while(my $query = CGI::Fast->new()) { $proc_manager->pm_pre_dispatch(); $count++; print <<TEXT; Content-Type: text/html <h1>hello</h1> $count <hr> TEXT print "$_ = $ENV{$_}<br>\n" foreach sort keys %ENV; print "<hr>\n"; print "$_ = ", $query->param($_), "<br>\n" foreach sort $query->pa +ram(); $proc_manager->pm_post_dispatch(); }
    Thread closed!