Peter Vereshagin > FCGI-Spawn > FCGI::Spawn

Download:
FCGI-Spawn-0.15.tar.gz

Dependencies

Annotate this POD

CPAN RT

Open  0
Report a bug
Module Version: 0.15   Source  

NAME ^

 FCGI::Spawn - process manager/application server for FastCGI protocol.

SYNOPSIS ^

Minimum unrecommended way to illustrate it working:

        use FCGI::Spawn;
        my $spawn = FCGI::Spawn->new();
        $spawn -> spawn;

Never put this in production use. This should be run as the web server's user id ( or another if umask isn't 022 ) and the web server should be configured to request its FastCGI on the default socket file name, the /tmp/spawner.sock. Consider to run as user other than web server's and setting up the proper sock_chmod/sock_chown parameters necessity. In the case if you request via TCP care should be taken on network security like DMZ/VPN/firewalls setup instead of sock_* parameters.

Tried to get know satisfaction with bugzilla... There's no place to dig out that Bugzilla doesn't work out with FastCGI other than Bugzilla's own Bugzilla though.

Tried the same with WebGUI.org. The versions since 6.9 went to require the mod_perl2 strictly. OK, but version 6.8 does work well at least as does at http://alpha.vereshagin.org. This is my ./run for daemontools by http://cr.yp.to:

#!/usr/bin/perl

package main; use strict; use warnings;

our $webguiRoot;

use Carp; $SIG{__DIE__} = sub{ print @_; print Carp::longmess };

BEGIN{ use Cwd qw/realpath getcwd/; use File::Basename qw/dirname/;

        $ENV{FCGI_SOCKET_PATH} = "/tmp/spawner.sock";
        
        $webguiRoot = realpath( dirname( __FILE__ )."/../../wg" );
        my $webguiLib = "$webguiRoot/lib";
        
        unshift( @INC, $webguiLib ) unless grep { $_ eq $webguiLib } @INC;
}
use FCGI::Spawn;
$FCGI::Spawn::fcgi = new CGI; eval ${ FCGI::Spawn::plsrc( $webguiRoot.'/../www/index.pl' ) }; die $@ if $@; undef $FCGI::Spawn::fcgi;

my $spawn = FCGI::Spawn->new({ # n_processes => 1, sock_chown => [qw/-1 27534/], sock_chmod => 0660, }, ); $spawn -> spawn;

1;

And, the minimum suggested way to spawn your FastCGI Perl scripts is as follows:

        #!/usr/bin/perl -w
        $ENV{FCGI_SOCKET_PATH} = "/path/to/spawner.sock";
        #       unshift @INC, "path/to/patched/CGI.pm"; # if need CGI.pm to work in sources
        eval( "use FCGI::Spawn;" );
        my $spawn = FCGI::Spawn->new({ n_processes => 7
                });
        $spawn -> spawn;

Here is the one more easy way to posess the daemontools facilities:

        $ cat ./env/FCGI_SOCKET_PATH
        /tmp/spawner.sock
        $ cat ./run
        #!/bin/sh
        exec 2>&1
        exec envdir ./env su fcgi -c '
          ./fcgi-run 
        '
        $ cat ./fcgi-run
        #!/usr/bin/perl -w
        use FCGI::Spawn;
        my $spawn = FCGI::Spawn->new();
        $spawn -> spawn;

A few more notes:

** You must configure socket with %ENV and tweak the patched CGI.pm, if need, at early before use FCGI::Spawn. The fisrt is achieved by mean of setting environment at behind in the shell or by mean of envdir feature of daemontools. %ENV and @INC can be tweaked in the special BEGIN block, as shown in examples above. You can eval use "FCGI::Spawn"; otherwise. And, you can delete $INC{ 'CGI.pm' } also if need to have patched CGI.pm to be compiled after teh unpatched system's one.

( I assume you need your own socket file name AND it must be tweakeable from inside of Perl. Second is to have CGI input to work in your applications )

This is because of setting up the socket communication in the CGI::Fast, which is the part of Perl core distribution, right in the BEGIN block, e. g. right before the compilation. But the one should restrictively point the socket file location right before the BEGIN block of the CGI::Fast. Well, without CGI::Fast there shouldn't be workable POST queries contents parsing, as it was up to FCGI::Spawn version 0.12. Another reason to do so is the need in your own CGI.pm patched with the CGI.pm.fcgi.spawn.patch applied to be used in your own library path that can be used as a string for unshift @INC.

** You should beware about CGI::Fast IS NOT included at the moment this module is being used, e. g. IS ABSENT in the %INC global hash. Because of that same reason.

** CGI scripts ( or CGI.pm ) must be tweaked to use $FCGI::Spawn::fcgi instead of new CGI or CGI->new. In other case they will not be able to process HTTP POST. Hope your code obfuscators are not that complex to allow such a tweak. ;-) At least it is obvious for FastCGI scripts to require FastCGI object if you use your application in any FastCGI environment. Otherwise, you can patch your CGI.pm with the supplied CGI.pm.fcgi.pm.patch, this can be your system CGI.pm, although it is not necessary. You can put the separate patched CGI.pm in the separate path for your perl sources and put that in teh begin of the @INC right before CGI.pm is used, even by dependencies. FCGI::Spawn (still) depends on it, so eval() the use FCGI::Spawn or put those actions in the BEGIN{}.

Thanks for understanding.

Why daemontools?

They have internal log-processing and automatical daemon restart on fault. Sure they posess control like stop/restart. Check em out and see. But those are not strictly necessary. Another reason is that i'm not experienced much with Perl daemons building like getting rid of STD* file handles and SIG* handling.

Why not mod_perl/mod_perl2/mod_fcgid?

Why still mod_perl?

Why not simply FCGI::ProcManager?

It seems to require too much in Perl knowledge from regular system administrator ( same as for startup.pl audit goes here ), in comparison to php's fastcgi mode. Even with that, it is not as mock as FCGI::Spawn for software developer. You will need to be me if you will need its features, if you are a sysadmin, while I'm the both.

DESCRIPTION ^

The overall idea is to make Perl server-side scripts as convinient for newbies and server administrators as PHP in FastCGI mode.

FCGI::Spawn is used to serve as a FastCGI process manager. Besides the features the FCGI::ProcManager posess itself, the FCGI::Spawn is targeted as web server admin understandable instance for building the own fastcgi server with copy-on-write memory sharing among forks and with single input parameters like processes number and maximum requests per fork.

Another thing to mention is that it is able to execute any file pointed by Web server ( FastCGI requester ). So we have the daemon that is hot ready for hosting providing :-)

The definitive care is taken in FCGI::Spawn on security. Besides the inode settings on local UNIX socket taken as input parameter, it is aware to avoid hosting users from changing the max_requests parameter meant correspondent to MaxRequests Apache's forked MPM parameter, and the respective current requests counter value as well.

The aforementioned max_requests parameter takes also care about the performance to avoid forks' memory leaks to consume all the RAM accounted on your hardware.

For shared hosting it is assumed that system administrator controls the process manager daemon script contents with those user hardware consumption limits and executes it with a user's credentials. E. g., the user should be able to send signal to the daemon to initiate graceful restart on his/her demand ( this is yet to be done ) or change the settings those administrator can specifically allow in the daemon starter script without restart ( both of those features are about to be done in the future ). For example, user may want to recompile the own sources and quickly change the clean_inc_hash for this.

The call stack lets you set up your own code reference for your scripts execution.

Seeking for convention between high preformance needs that the perl compile cache possesses and the convinience of debugging with recompilation on every request that php provides, the `stats` feature allows you not to recompile the tested source like those of DBI and frameworks but focus the development on your application development only, limiting the recompilation with your application(s) namespace(s) only. This may be useful in both development environment to make the recompilation yet faster and on a production host to make the details of code adaptaion to hosting clear in a much less time needed. This is new feature in v. 0.15 .

Every other thing is explained in FCGI::ProcManager docs.

PREREQUISITES ^

Be sure to have FCGI::ProcManager.

METHODS ^

class or instance

new({hash parameters})

Constructs a new process manager. Takes an option hash of the sock_name and sock_chown initial parameter values, and passes the entire hash rest to ProcManager's constructor. The parameters are:

Every other parameter is passed "as is" to the FCGI::ProcManager's constructor. Except for addition about the n_processes, which defaults to 5.

spawn

Fork a new process handling request like that being processed by web server.

callout

performs user's code execution. Isolates the max_requests and current requests counter values from changing in the user's source.

plsrc

Static function. Reads the supplied parameter up to "maxlength" bytes size chunked by "readchunk" bufer size and returns string reference. Deprecated and will be removed in future versions.

statnames_to_policy( 'mtime', 'ctime', ... );

Static function. Convert the list of file inode attributes' names checked by stat() builtin to the list of numbers for it described in the perldoc -f stat . In the case if the special word 'all' if met on the list, all the attributes are checked besides 'atime' (8). Also, you can define the order in which the stats are checked to reload perl modules: if the change is met, no further checks of this list for particular module on particular request are made as a decision to recompile that source is already taken. This is the convionient way to define the modules reload policy, the 'stat_policy' object property, among with the need in modules' reload itself by the 'stats' property checked as boolean only.

Thanks, Bugs, TODOs, Pros and Contras ( The Etcetera ) ^

The Inclusion

I had many debates and considerations about inclusion the end user scripts. Here's my own conclusions:

the default is to: do()

should be the best but not verbose enough and very definitive about exceptions. But the major in this is that it isolates $fcgi request lexical variable, so it is made global of this package.

require()

makes the every fork failed to incorporate the user's source to die() which is painful under heavy load.

system() or exec()

makes your FastCGI server to act as the simple CGI, except POST input is unavailable. Useful for debugging.

Mentioned plsrc() and eval() sub

reads user's source sized up to "maxlength" by buffers chunks of "readchunk" initial parameters. And, eval()'s it. Problem with this not only performance loss, but some thing do not work ou there, too, at least the built-in __FILE__ constant points to wrong location. ;-)

Deprecated and will be removed in future versions. One can write it by self defining the:

your own CODE ref

is able to be set by the "callout" initial parameter and/or "callout" object property.

The Bugs

Fresh bugs, fixes and features are to be available on git://github.com/petr999/fcgi-spawn.git .

Tested Environments

Nginx everywhere. Troubles met on passing %ENV variables responsible for CGI input, most of them concern POST requests: the HTTP_ prefix for *CONTENT_* and undescendence of configuration context with fastcgi_param-s.

The TODOs

Downloads

Tar.gz at CPAN, as always.

Sourceforge has latest development snapshot: http://fcgi-spawn.git.sourceforge.net/git/gitweb.cgi?p=fcgi-spawn/fcgi-spawn;a=snapshot;h=HEAD;sf=tgz .

Thanks

SkyRiver Studios for original fund of Perl(bugzilla) deployment on high loaded system.

Yuri@Reunion and MoCap.Ru for use cases, study review and suggestions on improvement.

AUTHOR, LICENSE ^

Peter Vereshagin <peter@vereshagin.org>, http://vereshagin.org.

License: same as FCGI::ProcManager's one.