about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <BOFH@YHBT.net>2023-09-07 23:53:58 +0000
committerEric Wong <BOFH@YHBT.net>2023-09-10 19:01:03 +0000
commitd67284a692683bca59effd9c0670bd5dd47e4fa3 (patch)
treebb6ddcfc5d5e6640415cb37114b1941d0e17ca06
parentd4514174ee7eadea89003f380acacf32d52acd9d (diff)
downloadunicorn-d67284a692683bca59effd9c0670bd5dd47e4fa3.tar.gz
I absolutely detest and regret adding this feature,
but I'm hell bent on supporting it until the end of days
because we don't break compatibility.
-rw-r--r--t/heartbeat-timeout.ru2
-rw-r--r--t/heartbeat-timeout.t69
-rwxr-xr-xt/t0004-heartbeat-timeout.sh69
3 files changed, 70 insertions, 70 deletions
diff --git a/t/heartbeat-timeout.ru b/t/heartbeat-timeout.ru
index 20a7938..3eeb5d6 100644
--- a/t/heartbeat-timeout.ru
+++ b/t/heartbeat-timeout.ru
@@ -7,6 +7,6 @@ run lambda { |env|
     sleep # in case STOP signal is not received in time
     [ 500, headers, [ "Should never get here\n" ] ]
   else
-    [ 200, headers, [ "#$$\n" ] ]
+    [ 200, headers, [ "#$$" ] ]
   end
 }
diff --git a/t/heartbeat-timeout.t b/t/heartbeat-timeout.t
new file mode 100644
index 0000000..1fcf21a
--- /dev/null
+++ b/t/heartbeat-timeout.t
@@ -0,0 +1,69 @@
+#!perl -w
+# Copyright (C) unicorn hackers <unicorn-public@yhbt.net>
+# License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
+use v5.14; BEGIN { require './t/lib.perl' };
+use autodie;
+use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC);
+mkdir "$tmpdir/alt";
+my $srv = tcp_server();
+my $u_conf = "$tmpdir/u.conf.rb";
+open my $fh, '>', $u_conf;
+print $fh <<EOM;
+pid "$tmpdir/pid"
+preload_app true
+stderr_path "$err_log"
+timeout 3 # WORST FEATURE EVER
+EOM
+close $fh;
+
+my $ar = unicorn(qw(-E none t/heartbeat-timeout.ru -c), $u_conf, { 3 => $srv });
+
+my $c = tcp_start($srv, 'GET /pid HTTP/1.0');
+my ($status, $hdr) = slurp_hdr($c);
+like($status, qr!\AHTTP/1\.[01] 200\b!, 'PID request succeeds');
+my $wpid = do { local $/; <$c> };
+like($wpid, qr/\A[0-9]+\z/, 'worker is running');
+
+my $t0 = clock_gettime(CLOCK_MONOTONIC);
+$c = tcp_start($srv, 'GET /block-forever HTTP/1.0');
+vec(my $rvec = '', fileno($c), 1) = 1;
+is(select($rvec, undef, undef, 6), 1, 'got readiness');
+$c->blocking(0);
+is(sysread($c, my $buf, 128), 0, 'got EOF response');
+my $elapsed = clock_gettime(CLOCK_MONOTONIC) - $t0;
+ok($elapsed > 3, 'timeout took >3s');
+
+my @timeout_err = slurp($err_log);
+truncate($err_log, 0);
+is(grep(/timeout \(\d+s > 3s\), killing/, @timeout_err), 1,
+    'noted timeout error') or diag explain(\@timeout_err);
+
+# did it respawn?
+$c = tcp_start($srv, 'GET /pid HTTP/1.0');
+($status, $hdr) = slurp_hdr($c);
+like($status, qr!\AHTTP/1\.[01] 200\b!, 'PID request succeeds');
+my $new_pid = do { local $/; <$c> };
+isnt($new_pid, $wpid, 'spawned new worker');
+
+diag 'SIGSTOP for 4 seconds...';
+$ar->do_kill('STOP');
+sleep 4;
+$ar->do_kill('CONT');
+for my $i (1..2) {
+        $c = tcp_start($srv, 'GET /pid HTTP/1.0');
+        ($status, $hdr) = slurp_hdr($c);
+        like($status, qr!\AHTTP/1\.[01] 200\b!,
+                "PID request succeeds #$i after STOP+CONT");
+        my $spid = do { local $/; <$c> };
+        is($new_pid, $spid, "worker pid unchanged after STOP+CONT #$i");
+        if ($i == 1) {
+                diag 'sleeping 2s to ensure timeout is not delayed';
+                sleep 2;
+        }
+}
+
+$ar->join('TERM');
+check_stderr;
+undef $tmpdir;
+
+done_testing;
diff --git a/t/t0004-heartbeat-timeout.sh b/t/t0004-heartbeat-timeout.sh
deleted file mode 100755
index 2965283..0000000
--- a/t/t0004-heartbeat-timeout.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-. ./test-lib.sh
-
-t_plan 11 "heartbeat/timeout test"
-
-t_begin "setup and startup" && {
-        unicorn_setup
-        echo timeout 3 >> $unicorn_config
-        echo preload_app true >> $unicorn_config
-        unicorn -D heartbeat-timeout.ru -c $unicorn_config
-        unicorn_wait_start
-}
-
-t_begin "read worker PID" && {
-        worker_pid=$(curl -sSf http://$listen/)
-        t_info "worker_pid=$worker_pid"
-}
-
-t_begin "sleep for a bit, ensure worker PID does not change" && {
-        sleep 4
-        test $(curl -sSf http://$listen/) -eq $worker_pid
-}
-
-t_begin "block the worker process to force it to die" && {
-        rm $ok
-        t0=$(unix_time)
-        err="$(curl -sSf http://$listen/block-forever 2>&1 || > $ok)"
-        t1=$(unix_time)
-        elapsed=$(($t1 - $t0))
-        t_info "elapsed=$elapsed err=$err"
-        test x"$err" != x"Should never get here"
-        test x"$err" != x"$worker_pid"
-}
-
-t_begin "ensure worker was killed" && {
-        test -e $ok
-        test 1 -eq $(grep timeout $r_err | grep killing | count_lines)
-}
-
-t_begin "ensure timeout took at least 3 seconds" && {
-        test $elapsed -ge 3
-}
-
-t_begin "we get a fresh new worker process" && {
-        new_worker_pid=$(curl -sSf http://$listen/)
-        test $new_worker_pid -ne $worker_pid
-}
-
-t_begin "truncate the server error log" && {
-        > $r_err
-}
-
-t_begin "SIGSTOP and SIGCONT on unicorn master does not kill worker" && {
-        kill -STOP $unicorn_pid
-        sleep 4
-        kill -CONT $unicorn_pid
-        sleep 2
-        test $new_worker_pid -eq $(curl -sSf http://$listen/)
-}
-
-t_begin "stop server" && {
-        kill -QUIT $unicorn_pid
-}
-
-t_begin "check stderr" && check_stderr
-
-dbgcat r_err
-
-t_done