[PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
This series requires the following patch:

  [PATCH 3/5] gitweb: Use nonlocal jump instead of 'exit' in die_error
  http://article.gmane.org/gmane.comp.version-control.git/145678

which is present as c42b00c commit in 'pu', as part of
'jn/gitweb-caching-prep' branch, which was merged into 'pu' at
97153ab7.


This patch adds support for FastCGI directly to gitweb.perl (so it
would be present in gitweb.cgi); selecting between FastCGI and CGI
is done via command-line switch (command-line option).  It uses
CGI::Fast, which is core Perl module.

It is port of old patch by Sam Vilain from 2006 to new gitweb
announced in

  "Re: gitweb testing with non-apache web server"
  http://article.gmane.org/gmane.comp.version-control.git/24718

The preparatory patch is refactoring work, to not need to have request
loop around large parts of code.  I think the preparatory patch makes
gitweb code more clean.


The alternate solution would be to add gitweb.fcgi wrapper, like e.g.:
in the following patch by Eric Wong

  "[PATCH 1/2] gitweb: add a simple wrapper for FCGI support"
  http://thread.gmane.org/gmane.comp.version-control.git/35920/focus=35921

which was part of the "[0/2 PATCH] FastCGI and nginx support for gitweb"
series.  (Note that the patch does 'do $gitweb_cgi;' without checking for
errors, see the bottom of `perldoc -f do` documentation on how it should
be done).


Some other references:
* "GitWeb in FastCGI" by Peter Vereshagin
  http://thread.gmane.org/gmane.comp.version-control.git/142132
* "FastCGI support in gitweb" by Juan Jose Comellas
  http://thread.gmane.org/gmane.comp.version-control.git/75704

Table of contents:
~~~~~~~~~~~~~~~~~~
 [PATCH/RFC 1/2] gitweb: Put all per-connection code in run() subroutine
 [PATCH/RFC 2/2] gitweb: Add support for FastCGI, using CGI::Fast

Jakub Narebski (1):
  gitweb: Put all per-connection code in run() subroutine

Sam Vilain (1):
  gitweb: Add support for FastCGI, using CGI::Fast

Diffstat:
~~~~~~~~~

 gitweb/gitweb.perl |  409 ++++++++++++++++++++++++++++++++--------------------
 1 files changed, 255 insertions(+), 154 deletions(-)

Diffstat -w:
~~~~~~~~~~~~
When ignoring whitespace change (reindenting)

 gitweb/gitweb.perl |  117 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 109 insertions(+), 8 deletions(-)

--
Jakub Narebski
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[PATCH/RFC 1/2] gitweb: Put all per-connection code in run() subroutine

Jakub Narębski
All code that is run per-connection (as opposed to those parts of gitweb
code that can be run once) is put into appropriate subroutines:
 - evaluate_uri
 - evaluate_gitweb_config
 - evaluate_git_version (here only because $GIT can be set in config)
 - check_loadavg (as soon as possible; $git_version must be defined)
 - evaluate_query_params (counterpart to evaluate_path_info)
 - evaluate_and_validate_params
 - evaluate_git_dir (requires $project)
 - configure_gitweb_features (@snapshot_fmts, $git_avatar)
 - dispatch (includes setting default $action)

The difference is best viewed with '-w', '--ignore-all-space' option,
because of reindent caused by putting code in subroutines.

Signed-off-by: Jakub Narebski <[hidden email]>
---
This patch requires the following commit from 'jn/gitweb-caching-prep' branch
c42b00c (gitweb: Use nonlocal jump instead of 'exit' in die_error, 2010-04-24)

This is an RFC patch because selecting which parts of gitweb code are
run-once, and which parts are per-request (and are to be put into
subroutines and run from run() subroutine) is at, least in part, a bit
subjective.

 gitweb/gitweb.perl |  359 ++++++++++++++++++++++++++++++----------------------
 1 files changed, 205 insertions(+), 154 deletions(-)

When ignoring whitespace changes (reindenting):

 gitweb/gitweb.perl |   67 +++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 59 insertions(+), 8 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 4074300..41bf992 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -28,34 +28,42 @@ BEGIN {
  CGI->compile() if $ENV{'MOD_PERL'};
 }
 
-our $cgi = new CGI;
 our $version = "++GIT_VERSION++";
-our $my_url = $cgi->url();
-our $my_uri = $cgi->url(-absolute => 1);
 
-# Base URL for relative URLs in gitweb ($logo, $favicon, ...),
-# needed and used only for URLs with nonempty PATH_INFO
-our $base_url = $my_url;
+our ($my_url, $my_uri, $base_url, $path_info, $home_link);
+sub evaluate_uri {
+ our $cgi;
 
-# When the script is used as DirectoryIndex, the URL does not contain the name
-# of the script file itself, and $cgi->url() fails to strip PATH_INFO, so we
-# have to do it ourselves. We make $path_info global because it's also used
-# later on.
-#
-# Another issue with the script being the DirectoryIndex is that the resulting
-# $my_url data is not the full script URL: this is good, because we want
-# generated links to keep implying the script name if it wasn't explicitly
-# indicated in the URL we're handling, but it means that $my_url cannot be used
-# as base URL.
-# Therefore, if we needed to strip PATH_INFO, then we know that we have
-# to build the base URL ourselves:
-our $path_info = $ENV{"PATH_INFO"};
-if ($path_info) {
- if ($my_url =~ s,\Q$path_info\E$,, &&
-    $my_uri =~ s,\Q$path_info\E$,, &&
-    defined $ENV{'SCRIPT_NAME'}) {
- $base_url = $cgi->url(-base => 1) . $ENV{'SCRIPT_NAME'};
+ our $my_url = $cgi->url();
+ our $my_uri = $cgi->url(-absolute => 1);
+
+ # Base URL for relative URLs in gitweb ($logo, $favicon, ...),
+ # needed and used only for URLs with nonempty PATH_INFO
+ our $base_url = $my_url;
+
+ # When the script is used as DirectoryIndex, the URL does not contain the name
+ # of the script file itself, and $cgi->url() fails to strip PATH_INFO, so we
+ # have to do it ourselves. We make $path_info global because it's also used
+ # later on.
+ #
+ # Another issue with the script being the DirectoryIndex is that the resulting
+ # $my_url data is not the full script URL: this is good, because we want
+ # generated links to keep implying the script name if it wasn't explicitly
+ # indicated in the URL we're handling, but it means that $my_url cannot be used
+ # as base URL.
+ # Therefore, if we needed to strip PATH_INFO, then we know that we have
+ # to build the base URL ourselves:
+ our $path_info = $ENV{"PATH_INFO"};
+ if ($path_info) {
+ if ($my_url =~ s,\Q$path_info\E$,, &&
+    $my_uri =~ s,\Q$path_info\E$,, &&
+    defined $ENV{'SCRIPT_NAME'}) {
+ $base_url = $cgi->url(-base => 1) . $ENV{'SCRIPT_NAME'};
+ }
  }
+
+ # target of the home link on top of all pages
+ our $home_link = $my_uri || "/";
 }
 
 # core git executable to use
@@ -70,9 +78,6 @@ our $projectroot = "++GITWEB_PROJECTROOT++";
 # the number is relative to the projectroot
 our $project_maxdepth = "++GITWEB_PROJECT_MAXDEPTH++";
 
-# target of the home link on top of all pages
-our $home_link = $my_uri || "/";
-
 # string of the home link on top of all pages
 our $home_link_str = "++GITWEB_HOME_LINK_STR++";
 
@@ -566,15 +571,18 @@ sub filter_snapshot_fmts {
  !$known_snapshot_formats{$_}{'disabled'}} @fmts;
 }
 
-our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
-our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
-# die if there are errors parsing config file
-if (-e $GITWEB_CONFIG) {
- do $GITWEB_CONFIG;
- die $@ if $@;
-} elsif (-e $GITWEB_CONFIG_SYSTEM) {
- do $GITWEB_CONFIG_SYSTEM;
- die $@ if $@;
+our ($GITWEB_CONFIG, $GITWEB_CONFIG_SYSTEM);
+sub evaluate_gitweb_config {
+ our $GITWEB_CONFIG = $ENV{'GITWEB_CONFIG'} || "++GITWEB_CONFIG++";
+ our $GITWEB_CONFIG_SYSTEM = $ENV{'GITWEB_CONFIG_SYSTEM'} || "++GITWEB_CONFIG_SYSTEM++";
+ # die if there are errors parsing config file
+ if (-e $GITWEB_CONFIG) {
+ do $GITWEB_CONFIG;
+ die $@ if $@;
+ } elsif (-e $GITWEB_CONFIG_SYSTEM) {
+ do $GITWEB_CONFIG_SYSTEM;
+ die $@ if $@;
+ }
 }
 
 # Get loadavg of system, to compare against $maxload.
@@ -600,13 +608,16 @@ sub get_loadavg {
 }
 
 # version of the core git binary
-our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
-$number_of_git_cmds++;
-
-$projects_list ||= $projectroot;
+our $git_version;
+sub evaluate_git_version {
+ our $git_version = qx("$GIT" --version) =~ m/git version (.*)$/ ? $1 : "unknown";
+ $number_of_git_cmds++;
+}
 
-if (defined $maxload && get_loadavg() > $maxload) {
- die_error(503, "The load average on the server is too high");
+sub check_loadavg {
+ if (defined $maxload && get_loadavg() > $maxload) {
+ die_error(503, "The load average on the server is too high");
+ }
 }
 
 # ======================================================================
@@ -693,11 +704,15 @@ our %allowed_options = (
 # should be single values, but opt can be an array. We should probably
 # build an array of parameters that can be multi-valued, but since for the time
 # being it's only this one, we just single it out
-while (my ($name, $symbol) = each %cgi_param_mapping) {
- if ($symbol eq 'opt') {
- $input_params{$name} = [ $cgi->param($symbol) ];
- } else {
- $input_params{$name} = $cgi->param($symbol);
+sub evaluate_query_params {
+ our $cgi;
+
+ while (my ($name, $symbol) = each %cgi_param_mapping) {
+ if ($symbol eq 'opt') {
+ $input_params{$name} = [ $cgi->param($symbol) ];
+ } else {
+ $input_params{$name} = $cgi->param($symbol);
+ }
  }
 }
 
@@ -844,149 +859,185 @@ sub evaluate_path_info {
  }
  }
 }
-evaluate_path_info();
 
-our $action = $input_params{'action'};
-if (defined $action) {
- if (!validate_action($action)) {
- die_error(400, "Invalid action parameter");
+our ($action, $project, $file_name, $file_parent, $hash, $hash_parent, $hash_base,
+     $hash_parent_base, @extra_options, $page, $searchtype, $search_use_regexp,
+     $searchtext, $search_regexp);
+sub evaluate_and_validate_params {
+ our $action = $input_params{'action'};
+ if (defined $action) {
+ if (!validate_action($action)) {
+ die_error(400, "Invalid action parameter");
+ }
  }
-}
 
-# parameters which are pathnames
-our $project = $input_params{'project'};
-if (defined $project) {
- if (!validate_project($project)) {
- undef $project;
- die_error(404, "No such project");
+ # parameters which are pathnames
+ our $project = $input_params{'project'};
+ if (defined $project) {
+ if (!validate_project($project)) {
+ undef $project;
+ die_error(404, "No such project");
+ }
  }
-}
 
-our $file_name = $input_params{'file_name'};
-if (defined $file_name) {
- if (!validate_pathname($file_name)) {
- die_error(400, "Invalid file parameter");
+ our $file_name = $input_params{'file_name'};
+ if (defined $file_name) {
+ if (!validate_pathname($file_name)) {
+ die_error(400, "Invalid file parameter");
+ }
  }
-}
 
-our $file_parent = $input_params{'file_parent'};
-if (defined $file_parent) {
- if (!validate_pathname($file_parent)) {
- die_error(400, "Invalid file parent parameter");
+ our $file_parent = $input_params{'file_parent'};
+ if (defined $file_parent) {
+ if (!validate_pathname($file_parent)) {
+ die_error(400, "Invalid file parent parameter");
+ }
  }
-}
 
-# parameters which are refnames
-our $hash = $input_params{'hash'};
-if (defined $hash) {
- if (!validate_refname($hash)) {
- die_error(400, "Invalid hash parameter");
+ # parameters which are refnames
+ our $hash = $input_params{'hash'};
+ if (defined $hash) {
+ if (!validate_refname($hash)) {
+ die_error(400, "Invalid hash parameter");
+ }
  }
-}
 
-our $hash_parent = $input_params{'hash_parent'};
-if (defined $hash_parent) {
- if (!validate_refname($hash_parent)) {
- die_error(400, "Invalid hash parent parameter");
+ our $hash_parent = $input_params{'hash_parent'};
+ if (defined $hash_parent) {
+ if (!validate_refname($hash_parent)) {
+ die_error(400, "Invalid hash parent parameter");
+ }
  }
-}
 
-our $hash_base = $input_params{'hash_base'};
-if (defined $hash_base) {
- if (!validate_refname($hash_base)) {
- die_error(400, "Invalid hash base parameter");
+ our $hash_base = $input_params{'hash_base'};
+ if (defined $hash_base) {
+ if (!validate_refname($hash_base)) {
+ die_error(400, "Invalid hash base parameter");
+ }
  }
-}
 
-our @extra_options = @{$input_params{'extra_options'}};
-# @extra_options is always defined, since it can only be (currently) set from
-# CGI, and $cgi->param() returns the empty array in array context if the param
-# is not set
-foreach my $opt (@extra_options) {
- if (not exists $allowed_options{$opt}) {
- die_error(400, "Invalid option parameter");
- }
- if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
- die_error(400, "Invalid option parameter for this action");
+ our @extra_options = @{$input_params{'extra_options'}};
+ # @extra_options is always defined, since it can only be (currently) set from
+ # CGI, and $cgi->param() returns the empty array in array context if the param
+ # is not set
+ foreach my $opt (@extra_options) {
+ if (not exists $allowed_options{$opt}) {
+ die_error(400, "Invalid option parameter");
+ }
+ if (not grep(/^$action$/, @{$allowed_options{$opt}})) {
+ die_error(400, "Invalid option parameter for this action");
+ }
  }
-}
 
-our $hash_parent_base = $input_params{'hash_parent_base'};
-if (defined $hash_parent_base) {
- if (!validate_refname($hash_parent_base)) {
- die_error(400, "Invalid hash parent base parameter");
+ our $hash_parent_base = $input_params{'hash_parent_base'};
+ if (defined $hash_parent_base) {
+ if (!validate_refname($hash_parent_base)) {
+ die_error(400, "Invalid hash parent base parameter");
+ }
  }
-}
 
-# other parameters
-our $page = $input_params{'page'};
-if (defined $page) {
- if ($page =~ m/[^0-9]/) {
- die_error(400, "Invalid page parameter");
+ # other parameters
+ our $page = $input_params{'page'};
+ if (defined $page) {
+ if ($page =~ m/[^0-9]/) {
+ die_error(400, "Invalid page parameter");
+ }
  }
-}
 
-our $searchtype = $input_params{'searchtype'};
-if (defined $searchtype) {
- if ($searchtype =~ m/[^a-z]/) {
- die_error(400, "Invalid searchtype parameter");
+ our $searchtype = $input_params{'searchtype'};
+ if (defined $searchtype) {
+ if ($searchtype =~ m/[^a-z]/) {
+ die_error(400, "Invalid searchtype parameter");
+ }
  }
-}
 
-our $search_use_regexp = $input_params{'search_use_regexp'};
+ our $search_use_regexp = $input_params{'search_use_regexp'};
 
-our $searchtext = $input_params{'searchtext'};
-our $search_regexp;
-if (defined $searchtext) {
- if (length($searchtext) < 2) {
- die_error(403, "At least two characters are required for search parameter");
+ our $searchtext = $input_params{'searchtext'};
+ our $search_regexp;
+ if (defined $searchtext) {
+ if (length($searchtext) < 2) {
+ die_error(403, "At least two characters are required for search parameter");
+ }
+ $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
  }
- $search_regexp = $search_use_regexp ? $searchtext : quotemeta $searchtext;
 }
 
 # path to the current git repository
 our $git_dir;
-$git_dir = "$projectroot/$project" if $project;
+sub evaluate_git_dir {
+ our $git_dir = "$projectroot/$project" if $project;
+}
 
-# list of supported snapshot formats
-our @snapshot_fmts = gitweb_get_feature('snapshot');
-@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
+our (@snapshot_fmts, $git_avatar);
+sub configure_gitweb_features {
+ # list of supported snapshot formats
+ our @snapshot_fmts = gitweb_get_feature('snapshot');
+ @snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
 
-# check that the avatar feature is set to a known provider name,
-# and for each provider check if the dependencies are satisfied.
-# if the provider name is invalid or the dependencies are not met,
-# reset $git_avatar to the empty string.
-our ($git_avatar) = gitweb_get_feature('avatar');
-if ($git_avatar eq 'gravatar') {
- $git_avatar = '' unless (eval { require Digest::MD5; 1; });
-} elsif ($git_avatar eq 'picon') {
- # no dependencies
-} else {
- $git_avatar = '';
+ # check that the avatar feature is set to a known provider name,
+ # and for each provider check if the dependencies are satisfied.
+ # if the provider name is invalid or the dependencies are not met,
+ # reset $git_avatar to the empty string.
+ our ($git_avatar) = gitweb_get_feature('avatar');
+ if ($git_avatar eq 'gravatar') {
+ $git_avatar = '' unless (eval { require Digest::MD5; 1; });
+ } elsif ($git_avatar eq 'picon') {
+ # no dependencies
+ } else {
+ $git_avatar = '';
+ }
 }
 
 # dispatch
-if (!defined $action) {
- if (defined $hash) {
- $action = git_get_type($hash);
- } elsif (defined $hash_base && defined $file_name) {
- $action = git_get_type("$hash_base:$file_name");
- } elsif (defined $project) {
- $action = 'summary';
- } else {
- $action = 'project_list';
+sub dispatch {
+ if (!defined $action) {
+ if (defined $hash) {
+ $action = git_get_type($hash);
+ } elsif (defined $hash_base && defined $file_name) {
+ $action = git_get_type("$hash_base:$file_name");
+ } elsif (defined $project) {
+ $action = 'summary';
+ } else {
+ $action = 'project_list';
+ }
  }
+ if (!defined($actions{$action})) {
+ die_error(400, "Unknown action");
+ }
+ if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
+    !$project) {
+ die_error(400, "Project needed");
+ }
+ $actions{$action}->();
 }
-if (!defined($actions{$action})) {
- die_error(400, "Unknown action");
-}
-if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
-    !$project) {
- die_error(400, "Project needed");
+
+sub run {
+ our $t0 = [Time::HiRes::gettimeofday()]
+ if defined $t0;
+
+ evaluate_uri();
+ evaluate_gitweb_config();
+ evaluate_git_version();
+ check_loadavg();
+
+ # $projectroot and $projects_list might be set in gitweb config file
+ $projects_list ||= $projectroot;
+
+ evaluate_query_params();
+ evaluate_path_info();
+ evaluate_and_validate_params();
+ evaluate_git_dir();
+
+ configure_gitweb_features();
+
+ dispatch();
+
+ DONE_GITWEB:
+ 1;
 }
-$actions{$action}->();
-DONE_GITWEB:
-1;
+our $cgi = CGI->new();
+run();
 
 ## ======================================================================
 ## action links
--
1.7.0.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[RFC/PATCH 2/2] gitweb: Add support for FastCGI, using CGI::Fast

Jakub Narębski
In reply to this post by Jakub Narębski
From: Sam Vilain <[hidden email]>

Former run() subroutine got renamed to run_request().  The new run()
subroutine can run multiple requests at once if run as FastCGI script.

To run gitweb as FastCGI script you must specify '--fastcgi' / '-f'
command line option to gitweb, otherwise it runs as an ordinary CGI
script.

[jn: cherry picked from 56d7d436644ab296155a697552ea1345f2701620
 in http://utsl.gen.nz/gitweb/?p=gitweb which was originally based
 on v264 (2326acfa95ac86a53804ca8eeeb482c2f9265e34) by Kay Sievers;
 updated to reflect current gitweb code]

TODO: update 'gitweb/README' and/or 'gitweb/INSTALL' files.

Signed-off-by: Sam Vilain <[hidden email]>
Signed-off-by: Jakub Narebski <[hidden email]>
---
This is straighforward port of Sam Vilain patch to new gitweb code.

It is an RFC because while I have checked that it doesn't cause
problems when running without the '--fastcgi' parameter:
* as CGI script (from mod_cgi),
* as ModPerl::Registry script (from mod_perl),
* as standalone script configured via gitweb_config.perl
  (from command line),
* as PSGI script via gitweb.psgi wrapper (from plackup,
  using Plack::App::WrapCGI, which in turn uses CGI::Emulate::PSGI),
I haven't actually checked that it runs correctly with *FastCGI server*
(because I don't have one installed).

 gitweb/gitweb.perl |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 41bf992..a4194d7 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1012,7 +1012,7 @@ sub dispatch {
  $actions{$action}->();
 }
 
-sub run {
+sub run_request {
  our $t0 = [Time::HiRes::gettimeofday()]
  if defined $t0;
 
@@ -1032,11 +1032,61 @@ sub run {
  configure_gitweb_features();
 
  dispatch();
+}
+
+our $is_last_request = sub { 1 };
+our ($pre_dispatch_hook, $post_dispatch_hook, $pre_listen_hook);
+our $CGI = 'CGI';
+our $cgi;
+sub evaluate_argv {
+ return unless (@ARGV);
+
+ require Getopt::Long;
+ Getopt::Long::GetOptions(
+ 'fastcgi|fcgi|f' => sub {
+ require CGI::Fast;
+ our $CGI = 'CGI::Fast';
+
+ my $request_number = 0;
+ # let each child service 100 requests
+ our $is_last_request = sub { ++$request_number > 100 };
+ },
+ 'nproc|n=i' => sub {
+ my ($arg, $val) = @_;
+ return unless eval { require FCGI::ProcManager; 1; };
+ my $proc_manager = FCGI::ProcManager->new({
+ n_processes => $val,
+ });
+ our $pre_listen_hook    = sub { $proc_manager->pm_manage()        };
+ our $pre_dispatch_hook  = sub { $proc_manager->pm_pre_dispatch()  };
+ our $post_dispatch_hook = sub { $proc_manager->pm_post_dispatch() };
+ },
+ );
+}
+
+sub run {
+ evaluate_argv();
+
+ $pre_listen_hook->()
+ if $pre_listen_hook;
+
+ REQUEST:
+ while ($cgi = $CGI->new()) {
+ $pre_dispatch_hook->()
+ if $pre_dispatch_hook;
+
+ run_request();
+
+ $pre_dispatch_hook->()
+ if $post_dispatch_hook;
+
+ last REQUEST if ($is_last_request->());
+ }
 
  DONE_GITWEB:
  1;
 }
-our $cgi = CGI->new();
+
 run();
 
 ## ======================================================================
--
1.7.0.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

[RFC/PATCHv2 2/2] gitweb: Add support for FastCGI, using CGI::Fast

Jakub Narębski
From: Sam Vilain <[hidden email]>

Former run() subroutine got renamed to run_request().  The new run()
subroutine can run multiple requests at once if run as FastCGI script.

To run gitweb as FastCGI script you must specify '--fastcgi' / '-f'
command line option to gitweb, otherwise it runs as an ordinary CGI
script.

[jn: cherry picked from 56d7d436644ab296155a697552ea1345f2701620
 in http://utsl.gen.nz/gitweb/?p=gitweb which was originally based
 on v264 (2326acfa95ac86a53804ca8eeeb482c2f9265e34) by Kay Sievers;
 updated to reflect current gitweb code]

TODO: update 'gitweb/README' and/or 'gitweb/INSTALL' files.

Signed-off-by: Sam Vilain <[hidden email]>
Signed-off-by: Jakub Narebski <[hidden email]>
---
Changes since v1:
* Fix $pre_dispatch_hook -> $post_dispatch_hook typo.

* Leave DONE_GITWEB label in run_request() subroutine.  This way "HTTP
  exceptions" thrown using die_error(), such as '404 Not Found', would
  correctly end current request, instead of exiting FCGI script.

  Note that in original patch by Sam Vilain "HTTP exceptions" would
  not run $post_dispatch_hook.

 gitweb/gitweb.perl |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 41bf992..9a3eaf5 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1012,7 +1012,7 @@ sub dispatch {
  $actions{$action}->();
 }
 
-sub run {
+sub run_request {
  our $t0 = [Time::HiRes::gettimeofday()]
  if defined $t0;
 
@@ -1036,7 +1036,57 @@ sub run {
  DONE_GITWEB:
  1;
 }
-our $cgi = CGI->new();
+
+our $is_last_request = sub { 1 };
+our ($pre_dispatch_hook, $post_dispatch_hook, $pre_listen_hook);
+our $CGI = 'CGI';
+our $cgi;
+sub evaluate_argv {
+ return unless (@ARGV);
+
+ require Getopt::Long;
+ Getopt::Long::GetOptions(
+ 'fastcgi|fcgi|f' => sub {
+ require CGI::Fast;
+ our $CGI = 'CGI::Fast';
+
+ my $request_number = 0;
+ # let each child service 100 requests
+ our $is_last_request = sub { ++$request_number > 100 };
+ },
+ 'nproc|n=i' => sub {
+ my ($arg, $val) = @_;
+ return unless eval { require FCGI::ProcManager; 1; };
+ my $proc_manager = FCGI::ProcManager->new({
+ n_processes => $val,
+ });
+ our $pre_listen_hook    = sub { $proc_manager->pm_manage()        };
+ our $pre_dispatch_hook  = sub { $proc_manager->pm_pre_dispatch()  };
+ our $post_dispatch_hook = sub { $proc_manager->pm_post_dispatch() };
+ },
+ );
+}
+
+sub run {
+ evaluate_argv();
+
+ $pre_listen_hook->()
+ if $pre_listen_hook;
+
+ REQUEST:
+ while ($cgi = $CGI->new()) {
+ $pre_dispatch_hook->()
+ if $pre_dispatch_hook;
+
+ run_request();
+
+ $post_dispatch_hook->()
+ if $post_dispatch_hook;
+
+ last REQUEST if ($is_last_request->());
+ }
+}
+
 run();
 
 ## ======================================================================
--
1.7.0.1

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
In reply to this post by Jakub Narębski
On Fri, 7 May 2010, Jakub Narebski wrote:

> The alternate solution would be to add gitweb.fcgi wrapper, like e.g.:
> in the following patch by Eric Wong
>
>   "[PATCH 1/2] gitweb: add a simple wrapper for FCGI support"
>   http://thread.gmane.org/gmane.comp.version-control.git/35920/focus=35921
>
> which was part of the "[0/2 PATCH] FastCGI and nginx support for gitweb"
> series.  (Note that the patch does 'do $gitweb_cgi;' without checking for
> errors, see the bottom of `perldoc -f do` documentation on how it should
> be done).

I think a better solution here would be to use CGI::Compile instead
of 'do $gitweb_cgi;'.

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Eric Wong
Jakub Narebski <[hidden email]> wrote:

> On Fri, 7 May 2010, Jakub Narebski wrote:
>
> > The alternate solution would be to add gitweb.fcgi wrapper, like e.g.:
> > in the following patch by Eric Wong
> >
> >   "[PATCH 1/2] gitweb: add a simple wrapper for FCGI support"
> >   http://thread.gmane.org/gmane.comp.version-control.git/35920/focus=35921
> >
> > which was part of the "[0/2 PATCH] FastCGI and nginx support for gitweb"
> > series.  (Note that the patch does 'do $gitweb_cgi;' without checking for
> > errors, see the bottom of `perldoc -f do` documentation on how it should
> > be done).
>
> I think a better solution here would be to use CGI::Compile instead
> of 'do $gitweb_cgi;'.

Possibly, now that CGI::Compile exists.  Can that be used with a
standalone Perl HTTP server?

It's 2010 now and I have long abandoned FastCGI in favor of using HTTP
to the application backends.  In my experience, having only one
plain-text protocol for both frontend web serving and backend
application RPC makes development/monitoring/testing much easier.

I just use Ruby WEBrick nowadays for any instaweb instances I run to
share with a few cow-orkers.  I do a reasonable amount of development in
Ruby, so it's always installed and ready for me.  It would be nice if
there were something standalone and as ubiquitous as WEBrick in the Perl
world.

--
Eric Wong
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Ævar Arnfjörð Bjarmason
On Sun, May 9, 2010 at 09:31, Eric Wong <[hidden email]> wrote:
> I just use Ruby WEBrick nowadays for any instaweb instances I run to
> share with a few cow-orkers.  I do a reasonable amount of development in
> Ruby, so it's always installed and ready for me.  It would be nice if
> there were something standalone and as ubiquitous as WEBrick in the Perl
> world.

There is: http://search.cpan.org/perldoc?Plack

You can run applications under everything from stand-alone webservers
to cgi, fastcgi and mod_perl if you interface with Plack.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
In reply to this post by Eric Wong
On Sun, 9 May 2010, Eric Wong wrote:

> Jakub Narebski <[hidden email]> wrote:
>> On Fri, 7 May 2010, Jakub Narebski wrote:
>>
>>> The alternate solution would be to add gitweb.fcgi wrapper, like e.g.:
>>> in the following patch by Eric Wong
>>>
>>>   "[PATCH 1/2] gitweb: add a simple wrapper for FCGI support"
>>>   http://thread.gmane.org/gmane.comp.version-control.git/35920/focus=35921
>>>
>>> which was part of the "[0/2 PATCH] FastCGI and nginx support for gitweb"
>>> series.  (Note that the patch does 'do $gitweb_cgi;' without checking for
>>> errors, see the bottom of `perldoc -f do` documentation on how it should
>>> be done).
>>
>> I think a better solution here would be to use CGI::Compile instead
>> of 'do $gitweb_cgi;'.
>
> Possibly, now that CGI::Compile exists.  Can that be used with a
> standalone Perl HTTP server?

Yes, it can.  CGI::Compile is used for example by CGI::Emulate::PSGI,
and you can run PSGI app on standalone Perl web server (pure Perl
HTTP::Server::PSGI, or HTTP::Server::Simple::PSGI which in turn uses
HTTP::Server::Simple, or Starman, or Twiggy, or Perlbal).  CGI::Compile
just compiles given CGI script into a subroutine, which can be called
many times in a persistent web environment like FastCGI.

>
> It's 2010 now and I have long abandoned FastCGI in favor of using HTTP
> to the application backends.  In my experience, having only one
> plain-text protocol for both frontend web serving and backend
> application RPC makes development/monitoring/testing much easier.

Do you mean here standalone web server in the language of web application?

>
> I just use Ruby WEBrick nowadays for any instaweb instances I run to
> share with a few cow-orkers.  I do a reasonable amount of development in
> Ruby, so it's always installed and ready for me.  It would be nice if
> there were something standalone and as ubiquitous as WEBrick in the Perl
> world.

Modern Perl has PSGI/Plack (http://plackperl.org), which was inspired by
Python's WSGI and Ruby's Rack.  The Plack reference implementation includes
'plackup' tool (inspired by Ruby's 'rackup'), which can be used to run
a PSGI application on any supported web server (with Plackup's adapter),
like HTTP::Server::PSGI, HTTP::Server::Simple::PSGI, etc.

PSGI/Plack goal is to be THE superglue interface between perl web
application frameworks and web servers.


P.S. BTW, I use the following wrapper for gitweb.cgi (in gitweb.psgi)

-- 8< --
#!/usr/bin/env plackup

# gitweb - simple web interface to track changes in git repositories
#          PSGI wrapper (see http://plackperl.org)

use strict;
use warnings;

use Plack::Builder;
use Plack::App::WrapCGI;
use CGI::Emulate::PSGI 0.07; # minimum version required to work

use File::Spec;
# __DIR__ is taken from Dir::Self __DIR__ fragment
sub __DIR__ () {
        File::Spec->rel2abs(join '', (File::Spec->splitpath(__FILE__))[0, 1]);
}

builder {
        enable 'Static',
                path => sub { m!\.(js|css|png)$! && s!^/gitweb/!! }, root => __DIR__."/";
        Plack::App::WrapCGI->new(script => __DIR__."/gitweb.cgi")->to_app;
}

__END__
-- >8 --

Thanks to the she-bang line (I don't have plackup installed globally,
but it is in my $PATH) I can just run ./gitweb.psgi to start server
(http://0:5000/) with gitweb running.

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Peter Vereshagin
I'm face to face with Jakub who sold the world?
2010/05/09 14:39:23 +0200 Jakub Narebski <[hidden email]> => To Eric Wong :

JN> Yes, it can.  CGI::Compile is used for example by CGI::Emulate::PSGI,
JN> and you can run PSGI app on standalone Perl web server (pure Perl
JN> HTTP::Server::PSGI, or HTTP::Server::Simple::PSGI which in turn uses
JN> HTTP::Server::Simple, or Starman, or Twiggy, or Perlbal).  CGI::Compile
JN> just compiles given CGI script into a subroutine, which can be called
JN> many times in a persistent web environment like FastCGI.

Thanks a lot about that!
I took a quick look at the patches and see this:
- FastCGI people are not always happy with CGI.pm anmd thus with CGI::Fast that
  derives from it. They prefer CGI::Simple, e. g. for the Catalyst on fastcgi
and other CGI.pm replacements. Despite the CGI::Fast is somehow the part of the
perl core distribution the FCGI.pm and CGI.pm which are the required
dependencies are not. Needless to say that the CGI.pm is not at all ( because
it tries too much to be ) a 'killer app'. I myself is about to stop using
CGI::Fast in FCGI::Spawn in favor of regular FCGI.pm and the CGI.pm variant
chosen by the user. Needless to say that this can make the CGI.pm patching for
FCGI::Spawn unecessary.
- FCGI::ProcManager is a piece of cake in any way, but there are 'more than one
  way to do it' (c) and it should be mentioned on a docs as a dependency since
there are modules on CPAN too for the same purpose but promiseful of features
like OO/etc.

The special thank for getting rid of exit()!

I'd like to propose the Git to have the Perl interface for common functions
that can make it easy to create trhe bunch of tools like those made with
(likely XS'ed) SVN:* namespace, e. g. git-svn. It makes me wonder why gitweb is
packaged with Git but no Perl API seen: looks like its storage is simple enough
to realize all of that in PP. Don't just disappoint me saying that git is used
to be exec()'uted on some of the gitweb calls. ;)

73! Peter pgp: A0E26627 (4A42 6841 2871 5EA7 52AB  12F8 0CE1 4AAC A0E2 6627)
--
http://vereshagin.org
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
On Sun, 9 May 2010, Peter Vereshagin wrote:

> I'm face to face with Jakub who sold the world?
> 2010/05/09 14:39:23 +0200 Jakub Narebski <[hidden email]> => To Eric Wong :
>
> JN> Yes, it can.  CGI::Compile is used for example by CGI::Emulate::PSGI,
> JN> and you can run PSGI app on standalone Perl web server (pure Perl
> JN> HTTP::Server::PSGI, or HTTP::Server::Simple::PSGI which in turn uses
> JN> HTTP::Server::Simple, or Starman, or Twiggy, or Perlbal).  CGI::Compile
> JN> just compiles given CGI script into a subroutine, which can be called
> JN> many times in a persistent web environment like FastCGI.
>
> Thanks a lot about that!
>
> I took a quick look at the patches and see this:
> - FastCGI people are not always happy with CGI.pm and thus with CGI::Fast that
>   derives from it. They prefer CGI::Simple, e. g. for the Catalyst on fastcgi
>   and other CGI.pm replacements.

CGI::Simple is not in core.  For Catalyst folks it is not a problem,
because Catalyst (one of Perl MVC web frameworks) is not in core either.

>   Despite the CGI::Fast is somehow the part of the perl core distribution
>   the FCGI.pm and CGI.pm which are the required dependencies are not.

Actually both CGI and CGI::Fast are in Perl core distribution since
perl 5.004 (Perl 5.4.0).  I assume that CGI::Fast simply degrades to CGI
if FCGI module is not present.

FCGI is the single non-core dependency of CGI, see
  http://deps.cpantesters.org/?module=CGI;perl=latest
so when I upgraded CGI (locally, using cpan client and local::lib), I also
installed FCGI.

>   Needless to say that the CGI.pm is not at all (because
>   it tries too much to be) a 'killer app'. I myself is about to stop using
>   CGI::Fast in FCGI::Spawn in favor of regular FCGI.pm and the CGI.pm variant
>   chosen by the user. Needless to say that this can make the CGI.pm patching for
>   FCGI::Spawn unecessary.

That's nice.

What are required changes to gitweb to use FCGI::Spawn to run gitweb as
a FastCGI script?  Alternatively, how the wrapper script for gitweb
(gitweb.fcgi) to be run as FastCGI should look like to use FCGI::Spawn?

> - FCGI::ProcManager is a piece of cake in any way, but there are 'more than one
>   way to do it' (c) and it should be mentioned on a docs as a dependency since
>   there are modules on CPAN too for the same purpose but promiseful of features
>   like OO/etc.

As PATCH 2/2 was straighforward port of Sam Vilain patch, I don't even
know what exactly the part containing FCGI::ProcManager does.

Note however that FCGI::ProcManager is require'd on demand; you have to
run gitweb with '--nproc=<n>'.  Also if FCGI::ProcManager is not found,
then the '--nproc=<n>' command line option is a no-op (does nothing).

>
> The special thank for getting rid of exit()!

You are welcome.

>
> I'd like to propose the Git to have the Perl interface for common functions
> that can make it easy to create the bunch of tools like those made with
> (likely XS'ed) SVN::* namespace, e. g. git-svn.

From what I remember from watching questions and discussion here on git
mailing list, the SVN::* Subversion bindings (from subversion-perl package)
are serious PITA.

Git.pm started (by Petr Baudis) with XS parts, but because of lack of
Perl hacker their compilation was unportable (IIRC it required support
for -fPIC), and was therefore abandoned.  The difficulty of creating
Git::XS is exacerbated by the fact that there is no libgit to make
Perl bindings againts, although hopefully GSoC 2010 project "Completing
libgit2" would help.


Git.pm currently wraps git commands in a *portable* way; that was the
reason behind creating it, to e.g. not have to write the same workarounds
for ActiveState Perl.  The other reason was to have safe way of invoking
git commands.  There are some utility functions there, but not much.

The "Gitweb caching" GSoC 2008 project[1] by Lea Wiemann included
improvements to git Perl interface in the form of Git::Repo, Git::RepoRoot,
Git::Object, Git::Commit and Git::Tag.  They are available in Lea's
repository[2], but were not merged into git core.

[1]: http://git.wiki.kernel.org/index.php/SoC2008Projects#Gitweb_caching
[2]: http://repo.or.cz/w/git/gitweb-caching.git

>
> It makes me wonder why gitweb is packaged with Git but no Perl API seen:

If you ask why gitweb does not use Git.pm, the reason is twofold.

First, gitweb predates Git.pm.  It also used safe form of invokeing git
commands (list form of magic "-|" pipeline open) at least since b918298
(gitweb: Use list for of open for running git commands..., 2006-07-30),
and was intended to run on POSIX (like e.g. "/" as path separator) and
therefore ActiveState Perl workarounds were not needed.

Second, in a few places gitweb needs either to pipe output of git command
to other command (to compressor in snapshot, and newly introduced to
highlighter when syntax highlighting is turned on), or silence errors
redirecting STDERR to /dev/null (in 'object' action to check if object
exists).  This is not yet supported in Git.pm.

Note that using IPC::Run for piping git command output to other command
would be counter to gitweb's goal of minimal non-core dependencies.

> looks like its storage is simple enough
> to realize all of that in PP. Don't just disappoint me saying that git is used
> to be exec()'uted on some of the gitweb calls. ;)

Gitalist[3], which started as port of gitweb to Catalyst web framework,
uses Git::PurePerl, a pure Perl interface to Git repositories (which
was mostly based on Grit, a git Ruby library, which includes a partial
native Ruby implementation).  Or used to use; there was some discussion
whether to use Git::PurePerl or wrap git commands.

Note that Gitalist was based on IIRC 2008 version of gitweb, so while
it includes features that gitweb doesn't have, the opposite also might
be true (features in gitweb that Gitalist doesn't have).

Also performance matters for gitweb.

[3]: https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools#Gitalist
--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Peter Vereshagin
Hey Jakub don't wanna cause you pain but the big boys feel no sorrow!
2010/05/09 20:18:52 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :

Great! I was just about to ask on caching, etc. What a complex history on all
of that, will be on those tracks after some of my whiles. ;-)

JN> What are required changes to gitweb to use FCGI::Spawn to run gitweb as
JN> a FastCGI script?  Alternatively, how the wrapper script for gitweb
JN> (gitweb.fcgi) to be run as FastCGI should look like to use FCGI::Spawn?


By far it's only an exit() of the what I use (1.6.0.6):

--- /usr/local/share/examples/git/gitweb/gitweb.cgi     2010-02-25 13:49:30.068287112 +0300
+++ www/gitweb.cgi      2010-03-13 14:28:45.326244103 +0300
@@ -933,7 +933,7 @@
        die_error(400, "Project needed");
 }
 $actions{$action}->();
-exit;
+#      exit;
 
 ## ======================================================================
 ## action links
@@ -3371,7 +3371,7 @@
 </div>
 EOF
        git_footer_html();
-       exit;
+#              exit;
 }
 
 ## ----------------------------------------------------------------------


but it's probably even not necessary with -e parameter:
http://search.cpan.org/~veresc/FCGI-Spawn-0.16.1/fcgi_spawn#Command_line_options
which is definitely required for bugzilla, the worst boy in that sandbox. The
parameter does just this:
===
my $cref = sub {
  if( 'FCGI::ProcManager' eq scalar caller ){
    CORE::exit @_;
  } else {
    no warnings;
    last CALLED_OUT;
  }
};
*CORE::GLOBAL::exit = $cref;
*CORE::GLOBAL::exit;
===
so this requires configuration
( $PREFIX/etc/fcgi_spawn/preload_nonprepared_01.pl, in my case ) for fcgi_spawn
daemon like this:
===
  $spawn->{ callout } =  sub{ do shift;
  CALLED_OUT:
  };
===
all of that is not needed without exit() in gitweb, now.

I didn't mean FCGI::PM is a problem by itself. The standalone gitweb daemon is
great thing for those who need such a choice. FCGI::Spawn is just for some
different task: to put several ( wish to say: any CGI app ) applications inside
the same fork()ed processes. It should be just obviously documented for a user
as a dependency for implementation of a gitweb fastcgi daemon. Although I'm not
sure if the FCGI::PM package should be a dependency for git package for any OS:
for those modules use()d in eval() my guess is: particular user's choice to be
offered.

So FCGI::PM usage I think makes a flavor taste for any daemon and thus should
be explicit. YMMV for those uninvolved in daemonizing, of course. ;-)

Is it probable that gitweb doesn't take any POSTs requests? The main trick
around FCGI::Spawn is the need to patch the CGI.pm but if that is the case...
I'd try to redefine the STDIN to /dev/null or zero so FCGI.Spawn.CGI.pm.patch
should be unnecessary for one who only wants to run the gitweb in FCGI::Spawn.
If switch to FCGI.pm will be way complicated to me.

73! Peter pgp: A0E26627 (4A42 6841 2871 5EA7 52AB  12F8 0CE1 4AAC A0E2 6627)
--
http://vereshagin.org
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
On Mon, 10 May 2010, Peter Vereshagin wrote:
> 2010/05/09 20:18:52 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
>
> Great! I was just about to ask on caching, etc. What a complex history on all
> of that, will be on those tracks after some of my whiles. ;-)

You can find current state of my take on gitweb output caching (based
on / inspired by work by John 'Warthog9' Hawley) in my repository on
repo.or.cz, in the 'gitweb/cache-kernel-pu' branch:

  http://repo.or.cz/w/git/jnareb-git.git  gitweb/cache-kernel-pu
 
You can find progress reports (and what current show-stoppers are) in
git mailing list archives.


Note that http://repo.or.cz does its own gitweb caching, IIRC by
caching Perl data, and only for 'projects_list' page (the most costly
one).

There was also "Gitweb caching" projects in GSoC 2008 by Lea Wiemann,
which IIUC cached output of git commands. This project was, I think,
completed but didn't get merged into git.

> JN> What are required changes to gitweb to use FCGI::Spawn to run gitweb as
> JN> a FastCGI script?  Alternatively, how the wrapper script for gitweb
> JN> (gitweb.fcgi) to be run as FastCGI should look like to use FCGI::Spawn?
>
> By far it's only an exit() of the what I use (1.6.0.6):

Why so old git?  Current version is git version 1.7.1

>
> --- /usr/local/share/examples/git/gitweb/gitweb.cgi     2010-02-25 13:49:30.068287112 +0300
> +++ www/gitweb.cgi                                      2010-03-13 14:28:45.326244103 +0300

Hrmph.  Why not use "git diff --no-index <file1> <file2>" here?

The Perl-aware equivalent of '-p' option of GNU diff, i.e. showing in
which function we are in hunk headers, would help here.

> @@ -933,7 +933,7 @@
>         die_error(400, "Project needed");
>  }
>  $actions{$action}->();
> -exit;
> +#      exit;

This 'exit' was here just in case there were some forgotten code below
this line outside subroutines (that should not be run).  It can be
safely removed.

>  
>  ## ======================================================================
>  ## action links
> @@ -3371,7 +3371,7 @@ sub die_error {

I have added my guess of in which subroutine this code is above.

>  </div>
>  EOF
>         git_footer_html();
> -       exit;
> +#              exit;
>  }

Err... and gitweb works correctly with this change?  This 'exit' was
required for die_error to function like 'die' in that it finishes
serving request, and should not continue subroutine it was called
from.

I have changed this 'exit' to non-local goto to toplevel.  It could be
done instead by redefining 'exit' subroutine, like shown below, but I
feel that would be hacky if you can change gitweb code (it is not
black box you should not touch).

>  
>  ## ----------------------------------------------------------------------
>
> but it's probably even not necessary with -e parameter:
> http://search.cpan.org/~veresc/FCGI-Spawn-0.16.1/fcgi_spawn#Command_line_options
> which is definitely required for bugzilla, the worst boy in that sandbox. The
> parameter does just this:
> ===
> my $cref = sub {
>   if ('FCGI::ProcManager' eq scalar caller) {
>     CORE::exit @_;
>   } else {
>     no warnings;
>     last CALLED_OUT;
>   }
> };
> *CORE::GLOBAL::exit = $cref;
> *CORE::GLOBAL::exit;
> ===

This is quite nice idea to replace 'exit' by subroutine that does
non-local jump to outside of application, at the end of request loop.
Such "monkey patching" is the only solution if you can't or shouldn't
modify application code (like FCGI::Spawn being generic solution).

> so this requires configuration
> ( $PREFIX/etc/fcgi_spawn/preload_nonprepared_01.pl, in my case ) for fcgi_spawn
> daemon like this:
> ===
>   $spawn->{ callout } =  sub{ do shift;
>   CALLED_OUT:
>   };
> ===

Here

   $spawn->{'callout'} = sub {
    my $cgi_app = shift;
    do $cgi_app;

        # this is needed for sane error handling
        die "Couldn't parse $cgi_app: $@" if $@;

   CALLED_OUT:
   };

could be simply replaced by

  use CGI::Compile;

  # ...

  $spawn->{'callout'} = \&{CGI::Compile->compile}

or something like that.  See CGI::Compile manpage and CGI::Compile source:
http://cpansearch.perl.org/src/MIYAGAWA/CGI-Compile-0.11/lib/CGI/Compile.pm

>
> All of that is not needed without exit() in gitweb, now.

BTW I wonder what are the consequences for performance on replacing
'exit' by non-local jump.  It can degrade performance a bit for gitweb
run as pure CGI (mod_cgi / mod_cgid), but should improve performance
for mod_perl, at least if there are more connections... unless
ModPerl::Registry does similar trick with exit().

>
> I didn't mean FCGI::PM is a problem by itself. The standalone gitweb daemon is
> great thing for those who need such a choice. FCGI::Spawn is just for some
> different task: to put several ( wish to say: any CGI app ) applications inside
> the same fork()ed processes. It should be just obviously documented for a user
> as a dependency for implementation of a gitweb fastcgi daemon. Although I'm not
> sure if the FCGI::PM package should be a dependency for git package for any OS:
> for those modules use()d in eval() my guess is: particular user's choice to be
> offered.
>
> So FCGI::PM usage I think makes a flavor taste for any daemon and thus should
> be explicit. YMMV for those uninvolved in daemonizing, of course. ;-)

Hmmm... is FCGI::Spawn really needed, or can it be replaced by simple
PSGI wrapper using either Plack::App::CGIBin,

  use Plack::App::CGIBin;
  use Plack::Builder;

  my $app = Plack::App::CGIBin->new(root => "/path/to/cgi-bin")->to_app;
  builder {
        mount "/cgi-bin" => $app;
  };

or Plack::App::WrapCGI plus Plack::App::URLMap, the last indirectly
via Plack::Builder DSL:

  use Plack::Builder;
  use Plack::App::WrapCGI;

  builder {
        mount "/foo" =>
                Plack::App::WrapCGI->new(script => "foo.cgi")->to_app;
        mount "/bar" =>
                Plack::App::WrapCGI->new(script => "bar.cgi")->to_app;
  };

>
> Is it probable that gitweb doesn't take any POSTs requests? The main trick
> around FCGI::Spawn is the need to patch the CGI.pm but if that is the case...
> I'd try to redefine the STDIN to /dev/null or zero so FCGI.Spawn.CGI.pm.patch
> should be unnecessary for one who only wants to run the gitweb in FCGI::Spawn.
> If switch to FCGI.pm will be way complicated to me.

Errr... excuse me, what you wanted to say in the paragraph above?

Gitweb doesn't use no POST requests: it is read-only web repository
browser... well, except for the 'show_ctags' action.
--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Peter Vereshagin
I know St. Peter won't call your name, Jakub!
2010/05/10 17:29:03 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
JN> On Mon, 10 May 2010, Peter Vereshagin wrote:
JN> > 2010/05/09 20:18:52 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
JN> >
JN> > Great! I was just about to ask on caching, etc. What a complex history on all
JN> > of that, will be on those tracks after some of my whiles. ;-)
JN>
JN> You can find current state of my take on gitweb output caching (based
JN> on / inspired by work by John 'Warthog9' Hawley) in my repository on
JN> repo.or.cz, in the 'gitweb/cache-kernel-pu' branch:
JN>
JN>   http://repo.or.cz/w/git/jnareb-git.git  gitweb/cache-kernel-pu
JN>  
JN> You can find progress reports (and what current show-stoppers are) in
JN> git mailing list archives.

I will.

JN> Note that http://repo.or.cz does its own gitweb caching, IIRC by
JN> caching Perl data, and only for 'projects_list' page (the most costly
JN> one).
JN>
JN> There was also "Gitweb caching" projects in GSoC 2008 by Lea Wiemann,
JN> which IIUC cached output of git commands. This project was, I think,
JN> completed but didn't get merged into git.
JN>
JN> > JN> What are required changes to gitweb to use FCGI::Spawn to run gitweb as
JN> > JN> a FastCGI script?  Alternatively, how the wrapper script for gitweb
JN> > JN> (gitweb.fcgi) to be run as FastCGI should look like to use FCGI::Spawn?
JN> >
JN> > By far it's only an exit() of the what I use (1.6.0.6):
JN>
JN> Why so old git?  Current version is git version 1.7.1

Update or die sounds too consumerical to me ;-)

JN>
JN> >
JN> > --- /usr/local/share/examples/git/gitweb/gitweb.cgi     2010-02-25 13:49:30.068287112 +0300
JN> > +++ www/gitweb.cgi                                      2010-03-13 14:28:45.326244103 +0300
JN>
JN> Hrmph.  Why not use "git diff --no-index <file1> <file2>" here?
JN>
JN> The Perl-aware equivalent of '-p' option of GNU diff, i.e. showing in
JN> which function we are in hunk headers, would help here.

It's obvious that I just made a more simple thing about this patch: grep exit
gitweb.cgi. Meat and potatoes ;-)

JN>
JN> > @@ -933,7 +933,7 @@
JN> >         die_error(400, "Project needed");
JN> >  }
JN> >  $actions{$action}->();
JN> > -exit;
JN> > +#      exit;
JN>
JN> This 'exit' was here just in case there were some forgotten code below
JN> this line outside subroutines (that should not be run).  It can be
JN> safely removed.
JN>
JN> >  
JN> >  ## ======================================================================
JN> >  ## action links
JN> > @@ -3371,7 +3371,7 @@ sub die_error {
JN>
JN> I have added my guess of in which subroutine this code is above.

Right.

JN>
JN> >  </div>
JN> >  EOF
JN> >         git_footer_html();
JN> > -       exit;
JN> > +#              exit;
JN> >  }
JN>
JN> Err... and gitweb works correctly with this change?  This 'exit' was
JN> required for die_error to function like 'die' in that it finishes
JN> serving request, and should not continue subroutine it was called
JN> from.

Does at least on 'non-existent diff' page:

http://gitweb.vereshagin.org/fcgiproxy/commitdiff/abcd

JN> I have changed this 'exit' to non-local goto to toplevel.  It could be
JN> done instead by redefining 'exit' subroutine, like shown below, but I
JN> feel that would be hacky if you can change gitweb code (it is not
JN> black box you should not touch).

Right, one shouldn't ever redefine perl built-in functions. I did only because
of no other way to 'get things working'

JN>
JN> >  
JN> >  ## ----------------------------------------------------------------------
JN> >
JN> > but it's probably even not necessary with -e parameter:
JN> > http://search.cpan.org/~veresc/FCGI-Spawn-0.16.1/fcgi_spawn#Command_line_options
JN> > which is definitely required for bugzilla, the worst boy in that sandbox. The
JN> > parameter does just this:
JN> > ===
JN> > my $cref = sub {
JN> >   if ('FCGI::ProcManager' eq scalar caller) {
JN> >     CORE::exit @_;
JN> >   } else {
JN> >     no warnings;
JN> >     last CALLED_OUT;
JN> >   }
JN> > };
JN> > *CORE::GLOBAL::exit = $cref;
JN> > *CORE::GLOBAL::exit;
JN> > ===
JN>
JN> This is quite nice idea to replace 'exit' by subroutine that does
JN> non-local jump to outside of application, at the end of request loop.
JN> Such "monkey patching" is the only solution if you can't or shouldn't
JN> modify application code (like FCGI::Spawn being generic solution).

Yes, this is quick-n-dirty to apply for those monkeys who are just busy to care
about re-writing CGI apps.

JN> > so this requires configuration
JN> > ( $PREFIX/etc/fcgi_spawn/preload_nonprepared_01.pl, in my case ) for fcgi_spawn
JN> > daemon like this:
JN> > ===
JN> >   $spawn->{ callout } =  sub{ do shift;
JN> >   CALLED_OUT:
JN> >   };
JN> > ===
JN>
JN> Here
JN>
JN>    $spawn->{'callout'} = sub {
JN>     my $cgi_app = shift;
JN>     do $cgi_app;
JN>
JN>         # this is needed for sane error handling
JN>         die "Couldn't parse $cgi_app: $@" if $@;
JN>
JN>    CALLED_OUT:
JN>    };

in a forked application, die() is a PITA on any reasonable load. It makes the
CoW-shared memory to be copied into separate area and being marked as unusable
before the process is dead. This is the only case I saw load averages on the
servers valued as crazy ~700.
So just exit there, not die. By far, die can not be redefined the same way as I
propose for exit in FCGI::Spawn.

JN>
JN> could be simply replaced by
JN>
JN>   use CGI::Compile;
JN>
JN>   # ...
JN>
JN>   $spawn->{'callout'} = \&{CGI::Compile->compile}
JN>
JN> or something like that.  See CGI::Compile manpage and CGI::Compile source:
JN> http://cpansearch.perl.org/src/MIYAGAWA/CGI-Compile-0.11/lib/CGI/Compile.pm
JN>
JN> >
JN> > All of that is not needed without exit() in gitweb, now.
JN>
JN> BTW I wonder what are the consequences for performance on replacing
JN> 'exit' by non-local jump.  It can degrade performance a bit for gitweb
JN> run as pure CGI (mod_cgi / mod_cgid), but should improve performance
JN> for mod_perl, at least if there are more connections... unless
JN> ModPerl::Registry does similar trick with exit().

I knew out about such a trick somewhere in modperlbook. For mod_perl, this
should be done in startup.pl

JN> > I didn't mean FCGI::PM is a problem by itself. The standalone gitweb daemon is
JN> > great thing for those who need such a choice. FCGI::Spawn is just for some
JN> > different task: to put several ( wish to say: any CGI app ) applications inside
JN> > the same fork()ed processes. It should be just obviously documented for a user
JN> > as a dependency for implementation of a gitweb fastcgi daemon. Although I'm not
JN> > sure if the FCGI::PM package should be a dependency for git package for any OS:
JN> > for those modules use()d in eval() my guess is: particular user's choice to be
JN> > offered.
JN> >
JN> > So FCGI::PM usage I think makes a flavor taste for any daemon and thus should
JN> > be explicit. YMMV for those uninvolved in daemonizing, of course. ;-)
JN>
JN> Hmmm... is FCGI::Spawn really needed, or can it be replaced by simple
JN> PSGI wrapper using either Plack::App::CGIBin,
JN>
JN>   use Plack::App::CGIBin;
JN>   use Plack::Builder;
JN>
JN>   my $app = Plack::App::CGIBin->new(root => "/path/to/cgi-bin")->to_app;
JN>   builder {
JN>         mount "/cgi-bin" => $app;
JN>   };

You use the predefined paths here on initialization. FCGI::Spawn knows about
the CGI application's path at the right moment it takes the request.

JN> or Plack::App::WrapCGI plus Plack::App::URLMap, the last indirectly
JN> via Plack::Builder DSL:
JN>
JN>   use Plack::Builder;
JN>   use Plack::App::WrapCGI;
JN>
JN>   builder {
JN>         mount "/foo" =>
JN>                 Plack::App::WrapCGI->new(script => "foo.cgi")->to_app;
JN>         mount "/bar" =>
JN>                 Plack::App::WrapCGI->new(script => "bar.cgi")->to_app;
JN>   };

Sounds no more simple than simplicity of php deployment. That is whom the
FCGI::Spawn combats for.
Probably, 'the directories and scripts cache' should help to defer such an
initialization? like it is done about the DBI handles in Apache::DBI. You can
perform that init on a first request per fork, and keep it built for all of the
process lifetime for the requests coming next.

JN> > Is it probable that gitweb doesn't take any POSTs requests? The main trick
JN> > around FCGI::Spawn is the need to patch the CGI.pm but if that is the case...
JN> > I'd try to redefine the STDIN to /dev/null or zero so FCGI.Spawn.CGI.pm.patch
JN> > should be unnecessary for one who only wants to run the gitweb in FCGI::Spawn.
JN> > If switch to FCGI.pm will be way complicated to me.
JN>
JN> Errr... excuse me, what you wanted to say in the paragraph above?

CGI::Fast use CGI.pm for POST input. With FCGI.pm I'll use CGI.pm for POST
input only on an application's demand in FCGI::Spawn.
In case of gitweb.cgi POST is not used. This makes the CGI.pm patch supplied
with FCGI::Spawn not needed.
But web user may send the POST request and FCGI::Spawn should feed a dummy
input for CGI.pm in the CGI script waiting for input from STDIN when request
method is POST.
Not sure if this feature is needed at all for FCGI::Spawn though.

JN> Gitweb doesn't use no POST requests: it is read-only web repository
JN> browser... well, except for the 'show_ctags' action.

Tag cloud? Is there an example of usable tag cloud on any public gitweb out
there?

73! Peter pgp: A0E26627 (4A42 6841 2871 5EA7 52AB  12F8 0CE1 4AAC A0E2 6627)
--
http://vereshagin.org
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Petr Baudis
On Tue, May 11, 2010 at 10:24:15AM +0400, Peter Vereshagin wrote:
> JN> Gitweb doesn't use no POST requests: it is read-only web repository
> JN> browser... well, except for the 'show_ctags' action.
>
> Tag cloud? Is there an example of usable tag cloud on any public gitweb out
> there?

See http://repo.or.cz/ for an example.

I don't think it's essential to support ctags under all configurations,
if doing so is too troublesome. But I expect our current GSoC to want
to add some more POST forms too.

--
                                Petr "Pasky" Baudis
When I feel like exercising, I just lie down until the feeling
goes away.  -- xed_over
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
In reply to this post by Peter Vereshagin
On Tue, 11 May 2010, Peter Vereshagin <[hidden email]> wrote:
> 2010/05/10 17:29:03 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
> > On Mon, 10 May 2010, Peter Vereshagin wrote:

> > >  ## ======================================================================
> > >  ## action links
> > > @@ -3371,7 +3371,7 @@ sub die_error {
> >
> > I have added my guess of in which subroutine this code is above.

[...]

> > >         git_footer_html();
> > > -       exit;
> > > +#              exit;
> > >  }
> >
> > Err... and gitweb works correctly with this change?  This 'exit' was
> > required for die_error to function like 'die' in that it finishes
> > serving request, and should not continue subroutine it was called
> > from.
>
> Does at least on 'non-existent diff' page:
>
> http://gitweb.vereshagin.org/fcgiproxy/commitdiff/abcd

Hmmm... strange that it works.
 
> > I have changed this 'exit' to non-local goto to toplevel.  It could be
> > done instead by redefining 'exit' subroutine, like shown below, but I
> > feel that would be hacky if you can change gitweb code (it is not
> > black box you should not touch).
>
> Right, one shouldn't ever redefine perl built-in functions. I did only because
> of no other way to 'get things working'

Why not?  For example CGI::Carp redefines 'die' to log errors.

  BEGIN {
    require Carp;
    *CORE::GLOBAL::die = \&CGI::Carp::die;
  }

Sub::Uplevel and Test::Exception redefines 'caller' (perhaps locally).
CGI::Compile redefines 'exit':

  our $USE_REAL_EXIT;
  BEGIN {
      $USE_REAL_EXIT = 1;
      *CORE::GLOBAL::exit = sub (;$) {
          my $exit_code = shift;

          CORE::exit(defined $exit_code ? $exit_code : 0) if $USE_REAL_EXIT;

          die [ "EXIT\n", $exit_code || 0 ]
      };
  }


> > This is quite nice idea to replace 'exit' by subroutine that does
> > non-local jump to outside of application, at the end of request loop.
> > Such "monkey patching" is the only solution if you can't or shouldn't
> > modify application code (like FCGI::Spawn being generic solution).
>
> Yes, this is quick-n-dirty to apply for those monkeys who are just busy to care
> about re-writing CGI apps.

Errr... "monkey patching" is the name of technique of extending and
modifying runtime code in dynamic languages, see

  http://en.wikipedia.org/wiki/Monkey_patch
 
Although I am not entirely sure if I correctly applied this name to
described (used) techique.

> > Here
> >
> >    $spawn->{'callout'} = sub {
> >     my $cgi_app = shift;
> >     do $cgi_app;
> >
> >     # this is needed for sane error handling
> >     die "Couldn't parse $cgi_app: $@" if $@;
> >
> >    CALLED_OUT:
> >    };
>
> In a forked application, die() is a PITA on any reasonable load. It makes the
> CoW-shared memory to be copied into separate area and being marked as unusable
> before the process is dead. This is the only case I saw load averages on the
> servers valued as crazy ~700.
>
> So just exit there, not die.

Well, it might be 'exit' not 'die', but you really, really need to check
if there were problems parsing file.  Otheriwse you can get error
messages somewhere further on that doesn't absolutely make sense.  

I know this from painful experience of trying to find bug in a
test... when the error was in parsing file in 'do $file;'.

> By far, die can not be redefined the same way as I propose for exit in
> FCGI::Spawn.

It can't?  CGI::Carp redefines 'die'.
 

> > > [...] FCGI::Spawn is just for some different task: to put several
> > > (wish to say: any CGI app) applications inside the same fork()ed
> > > processes. [...]
> >
> > Hmmm... is FCGI::Spawn really needed, or can it be replaced by simple
> > PSGI wrapper using either Plack::App::CGIBin,
> >
> >   use Plack::App::CGIBin;
> >   use Plack::Builder;
> >
> >   my $app = Plack::App::CGIBin->new(root => "/path/to/cgi-bin")->to_app;
> >   builder {
> >         mount "/cgi-bin" => $app;
> >   };
>
> You use the predefined paths here on initialization. FCGI::Spawn knows about
> the CGI application's path at the right moment it takes the request.

No, you need to provide only *root*, i.e. where Perl CGI applications
are, so that e.g. accessing 'http://0:5000/cgi-bin/foo/bar.cgi' would
run PSGI-ized (via CGI::Emulate::PSGI) '/path/to/cgi-bin/foo/bar.cgi'
application.

You don't need to mount it at "/cgi-bin", you can just

  builder {
        $app;
  }

or even without it ($app should be the last expression).


Or did you mean here something like mod_rewrite, or
Plack::Middleware::Rewrite?

[...]  
> > Gitweb doesn't use no POST requests: it is read-only web repository
> > browser... well, except for the 'show_ctags' action.
>
> Tag cloud? Is there an example of usable tag cloud on any public gitweb out
> there?

Tag cloud are optional feature in stock gitweb, named 'ctag' in %feature
hash.  It is disabled by default.  If I understand correctly POST is
used here to populate which tags one wants to use... but perhaps GET
request would be enough here (at the cost of less readable URL).

See http://repo.or.cz for example usage of this feature.

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Peter Vereshagin
I know St. Peter won't call your name, Jakub!
2010/05/11 12:58:50 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
JN> > > I have added my guess of in which subroutine this code is above.
JN>
JN> [...]
JN> > > >         git_footer_html();
JN> > > > -       exit;
JN> > > > +#              exit;
JN> > > >  }
JN> > >
JN> > > Err... and gitweb works correctly with this change?  This 'exit' was
JN> > > required for die_error to function like 'die' in that it finishes
JN> > > serving request, and should not continue subroutine it was called
JN> > > from.
JN> >
JN> > Does at least on 'non-existent diff' page:
JN> >
JN> > http://gitweb.vereshagin.org/fcgiproxy/commitdiff/abcd
JN>
JN> Hmmm... strange that it works.

just break it (c) ;-)
There are many other cases for this function to use, I just don't care. It's
all yet readonly after all ;-)

JN>  
JN> > > I have changed this 'exit' to non-local goto to toplevel.  It could be
JN> > > done instead by redefining 'exit' subroutine, like shown below, but I
JN> > > feel that would be hacky if you can change gitweb code (it is not
JN> > > black box you should not touch).
JN> >
JN> > Right, one shouldn't ever redefine perl built-in functions. I did only because
JN> > of no other way to 'get things working'
JN>
JN> Why not?  For example CGI::Carp redefines 'die' to log errors.

Ouch, sorry, I meant last() or something like that.
I just believe any non-system application development for end-user being a
non-developer doesn't need to redefine perl built-in functions. Just a sane
bone tone for common functioning in a sandbox.
For example, I remember the Linux kernel  ( or Glibc? ) was criticised much of
being possible to override the str*cmp() inside. Because most of the existing
commerceware were protected from copying by password, e. g. serial number, etc.
sometimes by authors. So criticants supposed it's impossible to 'protect' their
software this way. And thus Linux was 'bad'. ;-)
Nowadays we have all of those possible actions ( trying to investigate and
substitute the password hash in the str*cmp() called by user-space software )
classified by Crime Code and aoplied apparently widely. Kind of confessional
debates between those who suppose the potentially dangerous thing should be
restricted because it can be used as harm and those who use it regularly
without any idea to use it in any different dangerous way. Last time I saw them
on bbc about islam - 'hey, your islam spells to cut thievs' arms' - 'hey islam
of no danger, it's just very powerful and you shouldn't use it in dangerous
way'.
This will last for ages, anyway. You may find them even in "Just For Fun",
where the 'pubs' restricted topics' persist. Even there.
So one who use CORE:: namespace in their sources should always know it can be
grepped and considered as dangerous, especially if those are 3rd+ party
sources, not approved by any reasonable authority, and there are lots of such a
software off the shelves to choose. And most of them doesn't use to override
perl built-in functions. ;-)

JN>
JN>   BEGIN {
JN>     require Carp;
JN>     *CORE::GLOBAL::die = \&CGI::Carp::die;
JN>   }
JN>
JN> Sub::Uplevel and Test::Exception redefines 'caller' (perhaps locally).
JN> CGI::Compile redefines 'exit':
JN>
JN>   our $USE_REAL_EXIT;
JN>   BEGIN {
JN>       $USE_REAL_EXIT = 1;
JN>       *CORE::GLOBAL::exit = sub (;$) {
JN>           my $exit_code = shift;
JN>
JN>           CORE::exit(defined $exit_code ? $exit_code : 0) if $USE_REAL_EXIT;
JN>
JN>           die [ "EXIT\n", $exit_code || 0 ]
JN>       };
JN>   }
JN>
JN>
JN> > > This is quite nice idea to replace 'exit' by subroutine that does
JN> > > non-local jump to outside of application, at the end of request loop.
JN> > > Such "monkey patching" is the only solution if you can't or shouldn't
JN> > > modify application code (like FCGI::Spawn being generic solution).
JN> >
JN> > Yes, this is quick-n-dirty to apply for those monkeys who are just busy to care
JN> > about re-writing CGI apps.
JN>
JN> Errr... "monkey patching" is the name of technique of extending and
JN> modifying runtime code in dynamic languages, see
JN>
JN>   http://en.wikipedia.org/wiki/Monkey_patch

What's about 'patching'? Mokeys I meant to be the OpenBSD ( or non-OpenBSD ) crowd ;-)
http://article.gmane.org/gmane.linux.kernel/706950

JN> Although I am not entirely sure if I correctly applied this name to
JN> described (used) techique.


'Replace methods/attributes/functions at runtime, e.g. to stub out a function
during testing;'

sounds like 'dynamic modules reloading' to me. Yes, that is about FCGI::Spawn,
its 'stats' disablable feature

'Modify/extend behaviour of a third-party product without maintaining a private
copy of the source code; '

sounds like 'run any 3rd-party CGI app in FCGI::Spawn'

Yep, uncle Darwin cries out loud. ;-)

JN>
JN> > > Here
JN> > >
JN> > >    $spawn->{'callout'} = sub {
JN> > >     my $cgi_app = shift;
JN> > >     do $cgi_app;
JN> > >
JN> > >     # this is needed for sane error handling
JN> > >     die "Couldn't parse $cgi_app: $@" if $@;
JN> > >
JN> > >    CALLED_OUT:
JN> > >    };
JN> >
JN> > In a forked application, die() is a PITA on any reasonable load. It makes the
JN> > CoW-shared memory to be copied into separate area and being marked as unusable
JN> > before the process is dead. This is the only case I saw load averages on the
JN> > servers valued as crazy ~700.
JN> >
JN> > So just exit there, not die.
JN>
JN> Well, it might be 'exit' not 'die', but you really, really need to check
JN> if there were problems parsing file.  Otheriwse you can get error
JN> messages somewhere further on that doesn't absolutely make sense.  

php is very successful with this: it can put error messages to both STDOUT and
STDERR or separate log. FCGI::Spawn is the something about that because it's
the 'what the most people want' (c) Junio. ;-)
Anyway, if the file was not parsed, it did not change anything in perl's
compile-cache/variables and therefore it's quite safe for any othe application
on the same sandbox. Why should the fork die if some file gets unparsed?

JN> I know this from painful experience of trying to find bug in a
JN> test... when the error was in parsing file in 'do $file;'.

I handle them just fine like in any other CGI program using
CGI::Carp:fatalsToBrowser. Are you about to 'make test' via the http? ;-)

[...]

JN>   builder {
JN>         $app;
JN>   }

that's the wow to try. I will after some of my whiles.

JN> or even without it ($app should be the last expression).
JN> Or did you mean here something like mod_rewrite, or
JN> Plack::Middleware::Rewrite?

No, nginx rewrites just fine, it's a matter of another application level I
believe.
The scoop is meat and potatoes: here is the cgi app, just do it over FastCGI.
There are no such a thing as a mandatory mounts and paths tweaks in php's
fastcgi. Hope PSGI has no them either.

JN> [...]  
JN> > > Gitweb doesn't use no POST requests: it is read-only web repository
JN> > > browser... well, except for the 'show_ctags' action.
JN> > Tag cloud? Is there an example of usable tag cloud on any public gitweb out
JN> > there?
JN>
JN> Tag cloud are optional feature in stock gitweb, named 'ctag' in %feature
JN> hash.  It is disabled by default.  If I understand correctly POST is
JN> used here to populate which tags one wants to use... but perhaps GET
JN> request would be enough here (at the cost of less readable URL).
JN>
JN> See http://repo.or.cz for example usage of this feature.

Ouch, it was the first for me to look for them. It's just not named like that
there ( and looked like linkspam ;-. Anyway. user registration .cgi is a part
of gitweb distribution? It contains POST form and it's not  preferable stuff to
omit for too many cases to consider such a gitweb-based web site to be 'mostly
read-only' for a user.
Or those .cgi's are nothing in common with gitweb?

73! Peter pgp: A0E26627 (4A42 6841 2871 5EA7 52AB  12F8 0CE1 4AAC A0E2 6627)
--
http://vereshagin.org
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
On Tue, 11 May 2010, Peter Vereshagin wrote:
> 2010/05/11 12:58:50 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :

> > > > I have changed this 'exit' to non-local goto to toplevel.  It could be
> > > > done instead by redefining 'exit' subroutine, like shown below, but I
> > > > feel that would be hacky if you can change gitweb code (it is not
> > > > black box you should not touch).
> > >
> > > Right, one shouldn't ever redefine perl built-in functions. I did only because
> > > of no other way to 'get things working'
> >
> > Why not?  For example CGI::Carp redefines 'die' to log errors.
>
> Ouch, sorry, I meant 'last' or something like that.

"last" / "last LABEL" is a command, not a function, therefore you cannot
redefine it.

Well, perhaps you can with heavy hackery involving opcodes and the like,
or something debugger-like, or/and something like B::* modules, taking
over Perl parser.  See e.g. Devel::Declare or Template::Declare Perl
modules on CPAN. :-)

> I just believe any non-system application development for end-user being a
> non-developer doesn't need to redefine perl built-in functions. Just a sane
> bone tone for common functioning in a sandbox.
>
> For example, I remember the Linux kernel  ( or Glibc? ) was criticised much of
> being possible to override the str*cmp() inside. Because most of the existing
> commerceware were protected from copying by password, e. g. serial number, etc.
> sometimes by authors. So criticants supposed it's impossible to 'protect' their
> software this way. And thus Linux was 'bad'. ;-)

What about libsafe (?) and similar security solutions, which replace
str* functions from (g)libc with safer but slower counterparts?  What
about Dmalloc, Electric Fence and the like which replace malloc etc.?

> So one who use CORE:: namespace in their sources should always know it can be
> grepped and considered as dangerous, especially if those are 3rd+ party
> sources, not approved by any reasonable authority, and there are lots of such a
> software off the shelves to choose. And most of them doesn't use to override
> perl built-in functions. ;-)

It is true that messing with / overriding things from CORE:: (or
UNIVERSAL:: for OOP) namespace is dangerous, and should be avoided if
possible... but well, sometimes it is a best solution.
 
> > I know this from painful experience of trying to find bug in a
> > test... when the error was in parsing file in 'do $file;'.
>
> I handle them just fine like in any other CGI program using
> CGI::Carp:fatalsToBrowser. Are you about to 'make test' via the http? ;-)

I don't think you understand what I wanted to say there.

If you don't check if there were parse errors from 'do $file;', you can
get later some error message which is totally unrelated to the parsing
error.  If you don't know or forget that you should check $@ after
'do $file;', and are unlucky, you can chase elusive error from there
to kingdom come...

For example when debugging gitweb output caching code using automated
tests, I got the following error:

  'Undefined subroutine &GitwebCache::SimpleFileCache::compute called'

The subroutine was defined, but there was a bug in parsing included
file, so Perl didn't make it to definition of said compute() subroutine.

> [...]
>
> >   builder {
> >         $app;
> >   }
>
> that's the wow to try. I will after some of my whiles.

Check out http://plackperl.org, especially presentations and Perl Advent
Calendar which describes PSGI/Plack step by step (links at the bottom of
the page).
 

> > or even without it ($app should be the last expression).
> > Or did you mean here something like mod_rewrite, or
> > Plack::Middleware::Rewrite?
>
> No, nginx rewrites just fine, it's a matter of another application level I
> believe.
>
> The scoop is meat and potatoes: here is the CGI app, just do it over FastCGI.
> There are no such a thing as a mandatory mounts and paths tweaks in PHP's
> FastCGI. Hope PSGI has no them either.

PSGI is interface, Plack is reference implementation.  You can run PSGI
app on any supported web server; this includes running PSGI apps on
FastCGI.

> > > > Gitweb doesn't use no POST requests: it is read-only web repository
> > > > browser... well, except for the 'show_ctags' action.
> > >
> > > Tag cloud? Is there an example of usable tag cloud on any public gitweb out
> > > there?
> >
> > Tag cloud are optional feature in stock gitweb, named 'ctag' in %feature
> > hash.  It is disabled by default.  If I understand correctly POST is
> > used here to populate which tags one wants to use... but perhaps GET
> > request would be enough here (at the cost of less readable URL).
> >
> > See http://repo.or.cz for example usage of this feature.
>
> Ouch, it was the first for me to look for them. It's just not named like that
> there ( and looked like linkspam ;-. Anyway. user registration .cgi is a part
> of gitweb distribution? It contains POST form and it's not  preferable stuff to
> omit for too many cases to consider such a gitweb-based web site to be 'mostly
> read-only' for a user.
>
> Or those .cgi's are nothing in common with gitweb?

The repository management part of http://repo.or.cz is not part of
gitweb.  It is a separate tool, named Girocco.

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Peter Vereshagin
Hey Mr(s) Jakub show some good to me!
2010/05/11 15:51:15 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
JN> On Tue, 11 May 2010, Peter Vereshagin wrote:
JN> > 2010/05/11 12:58:50 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
JN>
JN> > > > > I have changed this 'exit' to non-local goto to toplevel.  It could be
JN> > > > > done instead by redefining 'exit' subroutine, like shown below, but I
JN> > > > > feel that would be hacky if you can change gitweb code (it is not
JN> > > > > black box you should not touch).
JN> > > >
JN> > > > Right, one shouldn't ever redefine perl built-in functions. I did only because
JN> > > > of no other way to 'get things working'
JN> > >
JN> > > Why not?  For example CGI::Carp redefines 'die' to log errors.
JN> >
JN> > Ouch, sorry, I meant 'last' or something like that.
JN>
JN> "last" / "last LABEL" is a command, not a function, therefore you cannot
JN> redefine it.

it's a flow control statement thus it is a built-in thing same way as any other
functions are explained in a 'perldoc -f'
Therefore it is treated by monkeys crowd as function. It's obvious for me to
stay out here ( here != maillist ) yet in such an environment.
Anyway, I compare last() here  with exit() and die() which look to user just
like the same kind of: the flow control statements. I guess any perl user who
makes things like gitweb ( at least as a CGI-only app ) shouldn't care about
such an internal difference of flow control statements those are
hidden/incapsulated inside the implementation of those statements?
Needless to mention that the 'last LABEL' ( goto, gosub, ... named them )  is a
bad and a very deprecated style which is every schoolboy is aware about
nowadays to keep from using in the application, not system, programming in imho
every language.

JN> Well, perhaps you can with heavy hackery involving opcodes and the like,
JN> or something debugger-like, or/and something like B::* modules, taking
JN> over Perl parser.  See e.g. Devel::Declare or Template::Declare Perl
JN> modules on CPAN. :-)
JN>
JN> > I just believe any non-system application development for end-user being a
JN> > non-developer doesn't need to redefine perl built-in functions. Just a sane
JN> > bone tone for common functioning in a sandbox.
JN> >
JN> > For example, I remember the Linux kernel  ( or Glibc? ) was criticised much of
JN> > being possible to override the str*cmp() inside. Because most of the existing
JN> > commerceware were protected from copying by password, e. g. serial number, etc.
JN> > sometimes by authors. So criticants supposed it's impossible to 'protect' their
JN> > software this way. And thus Linux was 'bad'. ;-)
JN>
JN> What about libsafe (?) and similar security solutions, which replace
JN> str* functions from (g)libc with safer but slower counterparts?  What

That was bad sound for commerceware vendors. Because such a in-core functions
substititions can make the user safer but not the investments ( targeted on
squeezing users' pursues).

JN> about Dmalloc, Electric Fence and the like which replace malloc etc.?

I think malloc implementation details cannot keep software's serial number from
being verified. ;-)
Back to perl built-ins: should it be normal if gitweb will be dependent on a
usage of a particular malloc implementation? In my perl, I can have a choice of
them. ;-)

JN> > So one who use CORE:: namespace in their sources should always know it can be
JN> > grepped and considered as dangerous, especially if those are 3rd+ party
JN> > sources, not approved by any reasonable authority, and there are lots of such a
JN> > software off the shelves to choose. And most of them doesn't use to override
JN> > perl built-in functions. ;-)
JN>
JN> It is true that messing with / overriding things from CORE:: (or
JN> UNIVERSAL:: for OOP) namespace is dangerous, and should be avoided if
JN> possible... but well, sometimes it is a best solution.

I think the state line between area to avoid one and the area where it can ever
happen to be the best of the solutions is built socially: it is where system
coder's work about daemon interfaces like the FCGI/PSGI/SCGI/etc. and the
applied coder one: the application architecture, used libraries, application
layers, etc.
This is just where FCGI::Spawn is about to help. Because 'regular system admin'
is typically unaware of details of usage of system daemon interfaces in perl.
But (s)he could be the perl application coder since perl is that easy as a
language tool. This is just who and when, and thus in what parts of the code
used by the same Perl interpreter shouldn't play with built-ins like the CORE::
namespace and thanks perl it can be easily grepped.

JN> > > I know this from painful experience of trying to find bug in a
JN> > > test... when the error was in parsing file in 'do $file;'.
JN> >
JN> > I handle them just fine like in any other CGI program using
JN> > CGI::Carp:fatalsToBrowser. Are you about to 'make test' via the http? ;-)
JN>
JN> I don't think you understand what I wanted to say there.
JN>
JN> If you don't check if there were parse errors from 'do $file;', you can
JN> get later some error message which is totally unrelated to the parsing
JN> error.  If you don't know or forget that you should check $@ after
JN> 'do $file;', and are unlucky, you can chase elusive error from there
JN> to kingdom come...

Got it, it's about the inclusion failure via the do() which is the development,
not a production, situation.
I think this should be an adjective noun to use the both strict and the warnings?
And yes, since it's about development but not production use, die is just fine
in the inclusion code like this:

eval( 'use Module;' ); die $@ if $@;

as always, require() can do the trick, not to mention usual

use Module;

This all will cause die() when it's necessary as only the application developer
knows how strict is the dependence on the Module. In some cases, application
can work without some Module but it's just better with it.

JN> For example when debugging gitweb output caching code using automated
JN> tests, I got the following error:
JN>
JN>   'Undefined subroutine &GitwebCache::SimpleFileCache::compute called'
JN>
JN> The subroutine was defined, but there was a bug in parsing included
JN> file, so Perl didn't make it to definition of said compute() subroutine.

What is the code? Where and what file was included via the do()?
Interesting situation. If the sub was compiled, was it present then in the
symbol table?
I can't see the code of ... GitwebCache::SimpleFileCache package to contain the do()?

JN> > [...]
JN> >
JN> > >   builder {
JN> > >         $app;
JN> > >   }
JN> >
JN> > that's the wow to try. I will after some of my whiles.
JN>
JN> Check out http://plackperl.org, especially presentations and Perl Advent
JN> Calendar which describes PSGI/Plack step by step (links at the bottom of
JN> the page).
JN>  
JN> > > or even without it ($app should be the last expression).
JN> > > Or did you mean here something like mod_rewrite, or
JN> > > Plack::Middleware::Rewrite?
JN> >
JN> > No, nginx rewrites just fine, it's a matter of another application level I
JN> > believe.
JN> >
JN> > The scoop is meat and potatoes: here is the CGI app, just do it over FastCGI.
JN> > There are no such a thing as a mandatory mounts and paths tweaks in PHP's
JN> > FastCGI. Hope PSGI has no them either.
JN>
JN> PSGI is interface, Plack is reference implementation.  You can run PSGI
JN> app on any supported web server; this includes running PSGI apps on
JN> FastCGI.

Existing problem FCGI::Spawn for is not the PSGI applications to be run as a
FastCGI, but the bunch of existing CGI.pm applications ( even gitorious ) need
to be more effective with the widest-spread protocol FastCGI. Best without any
patching of the application, deployed the same simple way as with apache's cgi
implementation.
Will check on this.

73! Peter pgp: A0E26627 (4A42 6841 2871 5EA7 52AB  12F8 0CE1 4AAC A0E2 6627)
--
http://vereshagin.org
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Ævar Arnfjörð Bjarmason
2010/5/13 Peter Vereshagin <[hidden email]>:

> Hey Mr(s) Jakub show some good to me!
> 2010/05/11 15:51:15 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
> JN> On Tue, 11 May 2010, Peter Vereshagin wrote:
> JN> > 2010/05/11 12:58:50 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
> JN>
> JN> > > > > I have changed this 'exit' to non-local goto to toplevel.  It could be
> JN> > > > > done instead by redefining 'exit' subroutine, like shown below, but I
> JN> > > > > feel that would be hacky if you can change gitweb code (it is not
> JN> > > > > black box you should not touch).
> JN> > > >
> JN> > > > Right, one shouldn't ever redefine perl built-in functions. I did only because
> JN> > > > of no other way to 'get things working'
> JN> > >
> JN> > > Why not?  For example CGI::Carp redefines 'die' to log errors.
> JN> >
> JN> > Ouch, sorry, I meant 'last' or something like that.
> JN>
> JN> "last" / "last LABEL" is a command, not a function, therefore you cannot
> JN> redefine it.
>
> it's a flow control statement thus it is a built-in thing same way as any other
> functions are explained in a 'perldoc -f'
> Therefore it is treated by monkeys crowd as function. It's obvious for me to
> stay out here ( here != maillist ) yet in such an environment.

These things are called "operators" in Perl, some of them (like exit)
you can redefine. Some (like last) you can't. At least not without
some deep magic.

> Anyway, I compare last() here  with exit() and die() which look to user just
> like the same kind of: the flow control statements. I guess any perl user who
> makes things like gitweb ( at least as a CGI-only app ) shouldn't care about
> such an internal difference of flow control statements those are
> hidden/incapsulated inside the implementation of those statements?
> Needless to mention that the 'last LABEL' ( goto, gosub, ... named them )  is a
> bad and a very deprecated style which is every schoolboy is aware about
> nowadays to keep from using in the application, not system, programming in imho
> every language.

`last LABEL' is not bad or deprecated. It's what you use to get out of
nested for-loops in Perl:

    OUTER: for my $i (1 .. 10) {
        for my $j (1 .. 10) {
            last OUTER if $i == 5 and $j == 5;
        }
    }

goto is also recommended in some cases in Perl. That's because it
doesn't do the same thing as in C:

    # Don't create a stack frame
    sub foo { goto &bar }

Anyway, arguing over which control flow operator is evil in an
imperitive language is just splitting hairs. Certain uses of them are
a bad idea, not the operators themselves.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH 0/2] gitweb: Add support for running gitweb as FastCGI script

Jakub Narębski
In reply to this post by Peter Vereshagin
On Thu, 13 May 2010, Peter Vereshagin wrote:
> 2010/05/11 15:51:15 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
>> On Tue, 11 May 2010, Peter Vereshagin wrote:
>>> 2010/05/11 12:58:50 +0200 Jakub Narebski <[hidden email]> => To Peter Vereshagin :
 

>>>>>> I have changed this 'exit' to non-local goto to toplevel.  It could be
>>>>>> done instead by redefining 'exit' subroutine, like shown below, but I
>>>>>> feel that would be hacky if you can change gitweb code (it is not
>>>>>> black box you should not touch).
>>>>>
>>>>> Right, one shouldn't ever redefine perl built-in functions. I did only because
>>>>> of no other way to 'get things working'
>>>>
>>>> Why not?  For example CGI::Carp redefines 'die' to log errors.
>>>
>>> Ouch, sorry, I meant 'last' or something like that.
>>
>> "last" / "last LABEL" is a command, not a function, therefore you cannot
>> redefine it.
>
> It's a flow control statement, thus it is a built-in thing; same way as any other
> functions are explained in a 'perldoc -f'.

`perldoc -f exit` says 'The exit() function ...', while `perldoc -f last`
says 'The "last" command is like the "break" statement in C ...'.

> Therefore it is treated by monkeys crowd as function. It's obvious for me to
> stay out here (here != maillist) yet in such an environment.

Sidenote: The 'Monkey patch' article on Wikipedia says that the
technique of adding method dirctly to class instead of subclassing was
originally called "guerilla patching", then it mutated into "gorilla
patching", and finally into "monkey patching".

> Anyway, I compare "last" here  with exit() and die() which look to user just
> like the same kind of: the flow control statements. I guess any Perl user who
> makes things like gitweb (at least as a CGI-only app) shouldn't care about
> such an internal difference of flow control statements those are
> hidden/incapsulated inside the implementation of those statements?

Perl hacker should know the difference between command such as "last"
and "next", and functions such as exit() and die().  Just like C
programmer should know the difference between "break" statement and
exit() function.

> Needless to mention that the 'last LABEL' ( goto, gosub, ... named them )  is a
> bad and a very deprecated style which is every schoolboy is aware about
> nowadays to keep from using in the application [...]

Not true.  The 'last LABEL;' command is very useful to exit nested
loops.  If used right it makes code much simpler (allowing to avoid
extra flag variable and/or complicating loop conditional).  If I
remember correctly in O.-J. Dahl, Edsger W. Dijkstra, C. A. R. Hoare
"Structured Programming" the programming language described includes
"break <n>" statement, with similar purpose as "last LABEL" in Perl.

Note also that Dijkstra wrote in seminal article "Go To Statement
Considered Harmful" that the problem with abused 'goto' is that it
compilcates and muddles control flow of program.  But there are
legitimate uses of 'goto' that make the program simpler to understand,
and not harder,... among those is handling exceptions.

>>>> I know this from painful experience of trying to find bug in a
>>>> test... when the error was in parsing file in 'do $file;'.
>>>
>>> I handle them just fine like in any other CGI program using
>>> CGI::Carp:fatalsToBrowser. Are you about to 'make test' via the http? ;-)
>>
>> I don't think you understand what I wanted to say there.
>>
>> If you don't check if there were parse errors from 'do $file;', you can
>> get later some error message which is totally unrelated to the parsing
>> error.  If you don't know or forget that you should check $@ after
>> 'do $file;', and are unlucky, you can chase elusive error from there
>> to kingdom come...
>
> Got it, it's about the inclusion failure via the do() which is the
> development, not a production, situation.

Yes, it is a problem mainly in developemtn, where changes to the file
included via "do <file>" might introduce parsing errors.

> I think this should be an adjective noun to use the both strict and
> the warnings?

The problem is that "do <file>;" is similar to "eval `cat <file>`;"
(except that it's more efficient and concise), it that it silences
parsing errors.  From `perldoc -f do`:

  If "do" cannot read the file, it returns undef and sets $! to the error.
  If "do" can read the file but cannot compile it, it returns undef and sets
  an error message in $@.   If the file is successfully compiled, "do"
  returns the value of the last expression evaluated.

> And yes, since it's about development but not production use, die is just fine
> in the inclusion code like this:
>
> eval( 'use Module;' ); die $@ if $@;

Wrong!
 
> as always, require() can do the trick, not to mention usual
>
> use Module;
>
> This all will cause die() when it's necessary as only the application developer
> knows how strict is the dependence on the Module. In some cases, application
> can work without some Module but it's just better with it.

First, both "use Module;" and "require Module;" (and "require '<file>';")
do automatic error checking and raise an exception if there is problem.

Second, "use Module <LIST>;" is equivalent to

  BEGIN { require Module; import Module <LIST>; }

and therefore it doesn't make sense to use it for conditional inclusion.


Therefore, to load Perl module / file, if you can 'die' you can simply
use

  require "<file>";

If you don't want to die, but want to know if loading and parsing file
succeeded or not, you should use the following syntax:

  if (eval { require "<file>"; 1 }) {
    ...
  } else {
    ...
  }

If you want to use 'do "<file>";' (it is preferred in some
circumstances), you really should check for error conditins:

  unless (my $return = do "<file>") {
    if ($@) {
       # couldn't parse <file>
    } elsif (!defined $return) {
       # couldn't do <file> (e.g. couldn't find <file>)
    }
    ...
  }

[...]
>> PSGI is interface, Plack is reference implementation.  You can run PSGI
>> app on any supported web server; this includes running PSGI apps on
>> FastCGI.
>
> Existing problem FCGI::Spawn for is not the PSGI applications to be run as a
> FastCGI, but the bunch of existing CGI.pm applications (even gitorious) need
> to be more effective with the widest-spread protocol FastCGI. Best without any
> patching of the application, deployed the same simple way as with apache's cgi
> implementation.

Gitorious is in Ruby, therefore is not a CGI.pm application, as it is
not even in Perl.

By using Plack::App::CGIBin you can load CGI scripts from a directory
and convert them into a <persistent> PSGI application.  You can use
Plack::App::WrapCGI to convert single CGI script into PSGI application.
You can use Plack::Buuilder's domain specific language to join (map)
together a bunch of PSGI applications (in different paths) in a single
app (via Plack::App::URLMap).

You can then run PSGI application (for example the PSGI app which loads
CGI apps via Plack::App::CGIBin) on any supported web server, which
includes FCGI (FastCGI).

--
Jakub Narebski
Poland
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [hidden email]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
12