Code

Merge branch 'jn/gitweb-return-or-exit-cleanup'
authorJunio C Hamano <gitster@pobox.com>
Tue, 22 Jun 2010 16:45:22 +0000 (09:45 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 22 Jun 2010 16:45:22 +0000 (09:45 -0700)
* jn/gitweb-return-or-exit-cleanup:
  gitweb: Return or exit after done serving request

Conflicts:
gitweb/gitweb.perl

1  2 
gitweb/gitweb.perl

index 9e5e0bf3ee6a86df6329da145f7f597e7abf491f,9d2b8c3b64fc50b96c7eb75c09520f3903d4845c..9446376535b1790c2400cd5bbc1e12f1a8b8f7c9
@@@ -1005,110 -981,36 +1005,119 @@@ sub handle_errors_html 
  set_message(\&handle_errors_html);
  
  # 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");
 +
 +sub run_request {
 +      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();
  }
 -if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
 -    !$project) {
 -      die_error(400, "Project needed");
 +
 +our $is_last_request = sub { 1 };
 +our ($pre_dispatch_hook, $post_dispatch_hook, $pre_listen_hook);
 +our $CGI = 'CGI';
 +our $cgi;
 +sub configure_as_fcgi {
 +      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 };
  }
 -$actions{$action}->();
 +sub evaluate_argv {
 +      my $script_name = $ENV{'SCRIPT_NAME'} || $ENV{'SCRIPT_FILENAME'} || __FILE__;
 +      configure_as_fcgi()
 +              if $script_name =~ /\.fcgi$/;
 +
 +      return unless (@ARGV);
 +
 +      require Getopt::Long;
 +      Getopt::Long::GetOptions(
 +              'fastcgi|fcgi|f' => \&configure_as_fcgi,
 +              '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;
 +}
 +
 +run();
  
 -DONE_GITWEB:
+ if (defined caller) {
+       # wrapped in a subroutine processing requests,
+       # e.g. mod_perl with ModPerl::Registry, or PSGI with Plack::App::WrapCGI
+       return;
+ } else {
+       # pure CGI script, serving single request
+       exit;
+ }
  ## ======================================================================
  ## action links