[Rt-commit] rt branch, 4.2/refactor-rt-server, created. rt-4.0.1-241-g25b8fea

Alex Vandiver alexmv at bestpractical.com
Thu Jul 21 13:47:53 EDT 2011


The branch, 4.2/refactor-rt-server has been created
        at  25b8fea1e3c0c1d8d6986e28f4896be6a4b0e5d4 (commit)

- Log -----------------------------------------------------------------
commit 533a3e327543254597ba0c61ad196063be98d524
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Jun 20 21:58:30 2011 -0400

    Refactor rt-server.in into RT::PlackRunner
    
    This properly detects --port, --listen, and --socket options, and falls
    back to $WebPort only when none are specified.  It also provides better
    handling for fastcgi, detecting when STDIN is a socket, and bailing with
    a correct error message if it has no other options to listen on.

diff --git a/lib/RT/PlackRunner.pm b/lib/RT/PlackRunner.pm
new file mode 100644
index 0000000..8a7ea3d
--- /dev/null
+++ b/lib/RT/PlackRunner.pm
@@ -0,0 +1,139 @@
+use warnings;
+use strict;
+
+package RT::PlackRunner;
+
+use base 'Plack::Runner';
+
+sub parse_options {
+    my $self = shift;
+    my @args = @_;
+    # handle "rt-server 8888" for back-compat, but complain about it
+    if (@args && $args[0] =~ m/^\d+$/) {
+        warn "Deprecated: please run $0 --port $ARGV[0] instead\n";
+        unshift @args, '--port';
+    }
+
+    $self->SUPER::parse_options(@args);
+
+    $self->{app}    ||= $self->app;
+    $self->{server} ||= $self->loader->guess;
+
+    my %args = @{$self->{options}};
+    if ($self->{server} eq "FCGI") {
+        # We deal with the possible failure modes of this in ->run
+    } elsif ($args{port}) {
+        $self->{explicit_port} = 1;
+        my $old_app = $self->{app};
+        $self->{app} = sub {
+            my $env = shift;
+            $env->{'rt.explicit_port'} = $args{port};
+            $old_app->($env, @_);
+        };
+    } else {
+        $self->set_options(port => (RT->Config->Get('WebPort') || '8080'));
+    }
+}
+
+# Override to not default to port 5000
+sub mangle_host_port_socket {
+    my($self, $host, $port, $socket, @listen) = @_;
+
+    for my $listen (reverse @listen) {
+        if ($listen =~ /:\d+$/) {
+            ($host, $port) = split /:/, $listen, 2;
+            $host = undef if $host eq '';
+        } else {
+            $socket ||= $listen;
+        }
+    }
+
+    unless (@listen) {
+        if ($socket) {
+            @listen = ($socket);
+        } elsif ($port) {
+            @listen = ($host ? "$host:$port" : ":$port");
+        }
+    }
+
+    return host => $host, port => $port, listen => \@listen, socket => $socket;
+}
+
+sub prepare_devel {
+    my($self, $app) = @_;
+    # Don't install the Lint, StackTrace, and AccessLog middleware
+
+    push @{$self->{options}}, server_ready => sub {
+        my($args) = @_;
+        my $name  = $args->{server_software} || ref($args);
+        my $host  = $args->{host}  || RT->Config->Get('WebDomain');
+        my $proto = $args->{proto} || 'http';
+        print STDERR "$name: Accepting connections at $proto://$host:$args->{port}/\n";
+    };
+
+    $app;
+}
+
+
+sub app {
+    require RT::Interface::Web::Handler;
+    my $app = RT::Interface::Web::Handler->PSGIApp;
+
+    if ($ENV{RT_TESTING}) {
+        my $screen_logger = $RT::Logger->remove('screen');
+        require Log::Dispatch::Perl;
+        $RT::Logger->add(
+            Log::Dispatch::Perl->new(
+                name      => 'rttest',
+                min_level => $screen_logger->min_level,
+                action    => {
+                    error    => 'warn',
+                    critical => 'warn'
+                }
+            )
+        );
+        require Plack::Middleware::Test::StashWarnings;
+        $app = Plack::Middleware::Test::StashWarnings->wrap($app);
+    }
+
+    return $app;
+}
+
+sub run {
+    my $self = shift;
+
+    my %args = @{$self->{options}};
+
+    # Plack::Handler::FCGI has its own catch for this, but doesn't
+    # notice that listen is an empty list, and we can also provide a
+    # better error message.
+    if ($self->{server} eq "FCGI" and not -S STDIN and not @{$args{listen}}) {
+        print STDERR "STDIN is not a socket, and no --listen, --socket, or --port provided\n";
+        exit 1;
+    }
+
+    eval { $self->SUPER::run(@_) };
+    my $err = $@;
+    exit 0 unless $err;
+
+    if ( $err =~ /listen/ ) {
+        print STDERR <<EOF;
+WARNING: RT couldn't start up a web server on port $args{port}.
+This is often the case if the port is already in use or you're running @{[$0]}
+as someone other than your system's "root" user.  You may also specify a
+temporary port with: $0 --port <port>
+EOF
+
+        if ($self->{explicit_port}) {
+            print STDERR
+                "Please check your system configuration or choose another port\n\n";
+        }
+        exit 1;
+    } else {
+        die
+            "Something went wrong while trying to run RT's standalone web server:\n\t"
+                . $err;
+    }
+}
+
+1;
diff --git a/sbin/rt-server.in b/sbin/rt-server.in
index bb4c664..1b0ae0b 100755
--- a/sbin/rt-server.in
+++ b/sbin/rt-server.in
@@ -92,7 +92,7 @@ my ($integrity, $state, $msg) = RT::Handle->CheckIntegrity;
 
 unless ( $integrity ) {
     print STDERR <<EOF;
-    
+
 RT couldn't connect to the database where tickets are stored.
 If this is a new installation of RT, you should visit the URL below
 to configure RT and initialize your database.
@@ -134,127 +134,20 @@ if ($RT::Handle) {
     undef $RT::Handle;
 }
 
-require RT::Interface::Web::Handler;
-my $app = RT::Interface::Web::Handler->PSGIApp;
-
-if ($ENV{RT_TESTING}) {
-    my $screen_logger = $RT::Logger->remove('screen');
-    require Log::Dispatch::Perl;
-    $RT::Logger->add(
-        Log::Dispatch::Perl->new(
-            name      => 'rttest',
-            min_level => $screen_logger->min_level,
-            action    => {
-                error    => 'warn',
-                critical => 'warn'
-            }
-        )
-    );
-    require Plack::Middleware::Test::StashWarnings;
-    $app = Plack::Middleware::Test::StashWarnings->wrap($app);
-}
-
+require RT::PlackRunner;
 # when used as a psgi file
 if (caller) {
-    return $app;
-}
-
-
-# load appropriate server
-
-require Plack::Runner;
-
-my $is_fastcgi = $0 =~ m/fcgi$/;
-my $r = Plack::Runner->new( $0 =~ 'standalone' ? ( server => 'Standalone' ) :
-                            $is_fastcgi        ? ( server => 'FCGI' )
-                                               : (),
-                            env => 'deployment' );
-
-# figure out the port
-my $port;
-
-# handle "rt-server 8888" for back-compat, but complain about it
-if ($ARGV[0] && $ARGV[0] =~ m/^\d+$/) {
-    warn "Deprecated: please run $0 --port $ARGV[0] instead\n";
-    unshift @ARGV, '--port';
+    return RT::PlackRunner->app;
 }
 
-my @args = @ARGV;
-
-use List::MoreUtils 'last_index';
-my $last_index = last_index { $_ eq '--port' } @args;
-
-my $explicit_port;
-
-if ( $last_index != -1 && $args[$last_index+1] =~ /^\d+$/ ) {
-    $explicit_port = $args[$last_index+1];
-    $port = $explicit_port;
 
-    # inform the rest of the system what port we manually chose
-    my $old_app = $app;
-    $app = sub {
-        my $env = shift;
-
-        $env->{'rt.explicit_port'} = $port;
-
-        $old_app->($env, @_);
-    };
-}
-else {
-    # default to the configured WebPort and inform Plack::Runner
-    $port = RT->Config->Get('WebPort') || '8080';
-    push @args, '--port', $port;
-}
+my $r = RT::PlackRunner->new( RT->InstallMode    ? ( server => 'Standalone' ) :
+                              $0 =~ /standalone/ ? ( server => 'Standalone' ) :
+                              $0 =~ /fcgi$/      ? ( server => 'FCGI',    env => "deployment" )
+                                                 : ( server => 'Starlet', env => "deployment" ) );
+$r->parse_options(@ARGV);
+$r->run;
 
-push @args, '--server', 'Standalone' if RT->InstallMode;
-push @args, '--server', 'Starlet' unless $r->{server} || grep { m/--server/ } @args;
-
-$r->parse_options(@args);
-
-delete $r->{options} if $is_fastcgi; ### mangle_host_port_socket ruins everything
-
-unless ($r->{env} eq 'development') {
-    push @{$r->{options}}, server_ready => sub {
-        my($args) = @_;
-        my $name  = $args->{server_software} || ref($args); # $args is $server
-        my $host  = $args->{host} || 0;
-        my $proto = $args->{proto} || 'http';
-        print STDERR "$name: Accepting connections at $proto://$host:$args->{port}/\n";
-    };
-}
-eval { $r->run($app) };
-if (my $err = $@) {
-    handle_startup_error($err);
-}
-
-exit 0;
-
-sub handle_startup_error {
-    my $err = shift;
-    if ( $err =~ /listen/ ) {
-        handle_bind_error();
-    } else {
-        die
-            "Something went wrong while trying to run RT's standalone web server:\n\t"
-            . $err;
-    }
-}
-
-
-sub handle_bind_error {
-
-    print STDERR <<EOF;
-WARNING: RT couldn't start up a web server on port @{[$port]}.
-This is often the case if the port is already in use or you're running @{[$0]} 
-as someone other than your system's "root" user.  You may also specify a
-temporary port with: $0 --port <port>
-EOF
-
-    if ($explicit_port) {
-        print STDERR
-            "Please check your system configuration or choose another port\n\n";
-    }
-}
 
 __END__
 

commit 25b8fea1e3c0c1d8d6986e28f4896be6a4b0e5d4
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Jul 21 13:12:56 2011 -0400

    Catch and fix var/ when rt-server is incorrectly run as root
    
    rt-server often gets incorrectly run as root for testing, leaving the
    mason cache later un-writable by the real web user (when run as fastcgi,
    for example).  Attempt to correct for this by chown'ing the var path to
    the web user and group if we were run as root.

diff --git a/sbin/rt-server.in b/sbin/rt-server.in
index 1b0ae0b..7ba983a 100755
--- a/sbin/rt-server.in
+++ b/sbin/rt-server.in
@@ -146,8 +146,15 @@ my $r = RT::PlackRunner->new( RT->InstallMode    ? ( server => 'Standalone' ) :
                               $0 =~ /fcgi$/      ? ( server => 'FCGI',    env => "deployment" )
                                                  : ( server => 'Starlet', env => "deployment" ) );
 $r->parse_options(@ARGV);
-$r->run;
 
+# Try to clean up wrong-permissions var/
+$SIG{INT} = sub {
+    local $@;
+    system("chown", "-R", "@WEB_USER@:@WEB_GROUP@", "@RT_VAR_PATH_R@");
+    exit 0;
+} if $> == 0;
+
+$r->run;
 
 __END__
 

-----------------------------------------------------------------------


More information about the Rt-commit mailing list