]> err.no Git - varnish/commitdiff
Use time-limited polling loops to verify parent and child startup and child
authordes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 20 Aug 2007 09:52:51 +0000 (09:52 +0000)
committerdes <des@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Mon, 20 Aug 2007 09:52:51 +0000 (09:52 +0000)
shutdown, instead of relying on unordered events.  Ignore anything that
appears on varnishd's std{out,err} except for an unexpected "child died",
which we handle by dying instead of emitting an event.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@1878 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-tools/regress/lib/Varnish/Test.pm
varnish-tools/regress/lib/Varnish/Test/Case.pm
varnish-tools/regress/lib/Varnish/Test/Varnish.pm

index d45e63d13829c18482eb771ee1025641086bc8eb..0a936265a25ac56698b2541d3d2871da0f9b5190 100644 (file)
@@ -117,7 +117,6 @@ sub start_engine($;@) {
 
     return if defined $self->{'engine'};
     $self->{'engine'} = Varnish::Test::Engine->new(@args);
-    $self->{'engine'}->run_loop('ev_varnish_started');
 }
 
 sub stop_engine($;$) {
index 8361977ffd989080c18019da8424b0cdd155c901..3c09a16a62598b03e6304c51bf8ea603a0f296b8 100644 (file)
@@ -103,7 +103,6 @@ sub init($) {
        $self->{'failed'} += 1;
        die "Unable to start child\n";
     }
-    $self->run_loop('ev_varnish_child_started');
 }
 
 sub fini($) {
@@ -113,13 +112,11 @@ sub fini($) {
 
     # Stop the worker process
     $varnish->stop_child();
-    $self->run_loop('ev_varnish_child_stopped');
 
     # Revert to initial VCL script
     no strict 'refs';
     if (${ref($self)."::VCL"}) {
        $varnish->use_vcl('boot');
-       $self->run_loop('ev_varnish_result');
     }
 
     delete $self->{'engine'}->{'case'};
index c5b5921ff963a5709d419c46f1b80b275e015218..d2af5e215f2b66d584cac274e08aa43ccb098e21 100644 (file)
@@ -113,44 +113,44 @@ sub new($$;$) {
        exec('varnishd', @opts);
        exit(1);
     }
-    else {
-       # Parent
-       $self->log('PID: ' . $pid);
 
-       close STDIN_READ;
-       close STDOUT_WRITE;
-       close STDERR_WRITE;
-
-       $self->{'pid'} = $pid;
-       $self->{'stdin'} = \*STDIN_WRITE;
-       $self->{'stdout'} = \*STDOUT_READ;
-       $self->{'stderr'} = \*STDERR_READ;
-
-       # Register the Varnish I/O-channels with the IO::Multiplex
-       # loop object.
-
-       $self->{'mux'}->add($self->{'stdin'});
-       $self->{'mux'}->set_callback_object($self, $self->{'stdin'});
-       $self->{'mux'}->add($self->{'stdout'});
-       $self->{'mux'}->set_callback_object($self, $self->{'stdout'});
-       $self->{'mux'}->add($self->{'stderr'});
-       $self->{'mux'}->set_callback_object($self, $self->{'stderr'});
-
-       # Wait up to 0.5 seconds for Varnish to accept our connection
-       # on the management port
-       for (my $i = 0; $i < 5; ++$i) {
-           last if $self->{'socket'} = IO::Socket::INET->
-               new(Type => SOCK_STREAM,
-                   PeerAddr => $engine->{'config'}->{'telnet_address'});
-           select(undef, undef, undef, 0.1);
-       }
-       if (!defined($self->{'socket'})) {
-           kill(15, delete $self->{'pid'});
-           die "Varnish did not start\n";
-       }
-       $self->{'mux'}->add($self->{'socket'});
-       $self->{'mux'}->set_callback_object($self, $self->{'socket'});
+    # Parent
+    $self->log('PID: ' . $pid);
+
+    close STDIN_READ;
+    close STDOUT_WRITE;
+    close STDERR_WRITE;
+
+    $self->{'pid'} = $pid;
+    $self->{'stdin'} = \*STDIN_WRITE;
+    $self->{'stdout'} = \*STDOUT_READ;
+    $self->{'stderr'} = \*STDERR_READ;
+
+    # Register the Varnish I/O-channels with the IO::Multiplex
+    # loop object.
+
+    $self->{'mux'}->add($self->{'stdin'});
+    $self->{'mux'}->set_callback_object($self, $self->{'stdin'});
+    $self->{'mux'}->add($self->{'stdout'});
+    $self->{'mux'}->set_callback_object($self, $self->{'stdout'});
+    $self->{'mux'}->add($self->{'stderr'});
+    $self->{'mux'}->set_callback_object($self, $self->{'stderr'});
+
+    # Wait up to 0.5 seconds for Varnish to accept our connection
+    # on the management port
+    for (my $i = 0; $i < 5; ++$i) {
+       last if $self->{'socket'} = IO::Socket::INET->
+           new(Type => SOCK_STREAM,
+               PeerAddr => $engine->{'config'}->{'telnet_address'});
+       select(undef, undef, undef, 0.1);
     }
+    if (!defined($self->{'socket'})) {
+       kill(15, delete $self->{'pid'});
+       die "Varnish did not start\n";
+    }
+    $self->{'mux'}->add($self->{'socket'});
+    $self->{'mux'}->set_callback_object($self, $self->{'socket'});
+    $self->{'state'} = 'stopped';
 
     return $self;
 }
@@ -191,6 +191,8 @@ sub send_command($@) {
        $self->{'engine'}->run_loop('ev_varnish_result',
                                    'ev_varnish_timeout');
     delete $self->{'pending'};
+    $self->log("result code $code")
+       if ($ev eq 'ev_varnish_result');
     return ($code, $text);
 }
 
@@ -213,7 +215,22 @@ sub start_child($) {
     die "already started\n"
        if $self->{'state'} eq "started";
 
-    return $self->send_command("start");
+    $self->{'state'} = 'starting';
+    my ($code, $text) = $self->send_command("start");
+    return ($code, $text)
+       unless ($code == 200);
+    for (my $n = 0; $n < 10; ++$n) {
+       my ($code, $text) = $self->send_command('status');
+       return ($code, $text)
+           unless ($code == 200);
+       if ($text =~ /state running/) {
+           $self->{'state'} = 'started';
+           return ($code, $text);
+       }
+       select(undef, undef, undef, 0.5);
+    }
+    $self->shutdown();
+    return (500, 'unable to start child');
 }
 
 sub stop_child($) {
@@ -223,7 +240,20 @@ sub stop_child($) {
     die "already stopped\n"
        if $self->{'state'} eq 'stopped';
 
-    return $self->send_command("stop");
+    $self->{'state'} eq 'stopping';
+    my ($code, $text) = $self->send_command("stop");
+    for (my $n = 0; $n < 10; ++$n) {
+       my ($code, $text) = $self->send_command('status');
+       return ($code, $text)
+           unless ($code == 200);
+       if ($text =~ /state stopped/) {
+           $self->{'state'} = 'stopped';
+           return ($code, $text);
+       }
+       select(undef, undef, undef, 0.5);
+    }
+    $self->shutdown();
+    return (500, 'unable to stop child');
 }
 
 sub set_param($$$) {
@@ -273,22 +303,22 @@ sub mux_input($$$$) {
            return;
        }
        # extract the response text (if any), then remove from $$data
-       my $text = substr($$data, length($line), $len);
-       substr($$data, 0, length($line) + $len + 1, '');
-
-       $self->{'engine'}->ev_varnish_result($code, $text);
+       $$data =~ s/^\Q$line\E\n(.{$len})\n//
+           or die "oops\n";
+       $self->{'engine'}->ev_varnish_result($code, $1);
     } else {
-       if ($$data =~ /^rolling\(2\)\.\.\./m) {
-           $self->{'state'} = 'stopped';
-           $self->{'engine'}->ev_varnish_started;
-       }
-       if ($$data =~ /Child starts/) {
-           $self->{'state'} = 'started';
-           $self->{'engine'}->ev_varnish_child_started;
-       }
-       if ($$data =~ /Child dies/) {
-           $self->{'state'} = 'stopped';
-           $self->{'engine'}->ev_varnish_child_stopped;
+       if ($$data =~ /Child died pid=(\d+) status=0x([0-9A-Fa-f]+)/) {
+           my ($pid, $status) = ($1, hex($2));
+           if ($pid != $self->{'pid'}) {
+               # shouldn't happen, but sometimes it does
+               $self->log("stray child $pid died with status $status");
+           } elsif ($self->{'state'} == 'stopping' ||
+               $self->{'state'} == 'stopped') {
+               # ignore
+           } else {
+               $self->{'state'} = 'stopped';
+               die "child died unexpectedly with status $status\n";
+           }
        }
        # XXX there might be more!
        $$data = '';