diff options
-rw-r--r-- | lib/PublicInbox/TestCommon.pm | 36 | ||||
-rw-r--r-- | t/httpd-unix.t | 35 |
2 files changed, 36 insertions, 35 deletions
diff --git a/lib/PublicInbox/TestCommon.pm b/lib/PublicInbox/TestCommon.pm index 1fdb5ebd..7b628769 100644 --- a/lib/PublicInbox/TestCommon.pm +++ b/lib/PublicInbox/TestCommon.pm @@ -24,6 +24,7 @@ BEGIN { run_script start_script key2sub xsys xsys_e xqx eml_load tick have_xapian_compact json_utf8 setup_public_inboxes create_inbox create_coderepo no_scm_rights + quit_waiter_pipe wait_for_eof tcp_host_port test_lei lei lei_ok $lei_out $lei_err $lei_opt test_httpd xbail require_cmd is_xdeeply tail_f ignore_inline_c_missing no_pollerfd no_coredump cfg_new); @@ -632,12 +633,28 @@ sub need_scm_rights () { '(mkdir -p ~/.cache/public-inbox/inline-c) OR Socket::MsgHdr missing'; } +# returns a pipe with FD_CLOEXEC disabled on the write-end +sub quit_waiter_pipe () { + use autodie qw(fcntl pipe); + pipe(my $r, my $w); + fcntl($w, F_SETFD, fcntl($w, F_GETFD, 0) & ~FD_CLOEXEC); + ($r, $w); +} + +sub wait_for_eof ($$;$) { + my ($io, $msg, $sec) = @_; + vec(my $rset = '', fileno($io), 1) = 1; + ok(select($rset, undef, undef, $sec // 9), "$msg (select)"); + is(my $line = <$io>, undef, "$msg EOF"); +} + sub test_lei { SKIP: { my ($cb) = pop @_; my $test_opt = shift // {}; local $lei_cwdfh; - opendir $lei_cwdfh, '.' or xbail "opendir .: $!"; + use autodie qw(mkdir open opendir); + opendir $lei_cwdfh, '.'; require_git(2.6, 1); my $mods = $test_opt->{mods} // [ 'lei' ]; require_mods(@$mods, 2); @@ -661,22 +678,25 @@ SKIP: { my $tmpdir = $test_opt->{tmpdir}; File::Path::mkpath($tmpdir) if defined $tmpdir; ($tmpdir, $for_destroy) = tmpdir unless $tmpdir; + my ($dead_r, $dead_w); state $persist_xrd = $ENV{TEST_LEI_DAEMON_PERSIST_DIR}; SKIP: { $ENV{TEST_LEI_ONESHOT} and xbail 'TEST_LEI_ONESHOT no longer supported'; my $home = "$tmpdir/lei-daemon"; - mkdir($home, 0700) or BAIL_OUT "mkdir: $!"; + mkdir($home, 0700); local $ENV{HOME} = $home; my $persist; if ($persist_xrd && !$test_opt->{daemon_only}) { $persist = $daemon_xrd = $persist_xrd; } else { $daemon_xrd = "$home/xdg_run"; - mkdir($daemon_xrd, 0700) or BAIL_OUT "mkdir: $!"; + mkdir($daemon_xrd, 0700); + ($dead_r, $dead_w) = quit_waiter_pipe; } local $ENV{XDG_RUNTIME_DIR} = $daemon_xrd; - $cb->(); + $cb->(); # likely shares $dead_w with lei-daemon + undef $dead_w; # so select() wakes up when daemon dies if ($persist) { # remove before ~/.local gets removed File::Path::rmtree([glob("$home/*")]); File::Path::rmtree("$home/.config"); @@ -693,14 +713,10 @@ SKIP: { } }; # SKIP for lei_daemon if ($daemon_pid) { - for (0..10) { - kill(0, $daemon_pid) or last; - tick; - } - ok(!kill(0, $daemon_pid), "$t daemon stopped"); + wait_for_eof($dead_r, 'daemon quit pipe'); no_coredump $tmpdir; my $f = "$daemon_xrd/lei/errors.log"; - open my $fh, '<', $f or BAIL_OUT "$f: $!"; + open my $fh, '<', $f; my @l = <$fh>; is_xdeeply(\@l, [], "$t daemon XDG_RUNTIME_DIR/lei/errors.log empty"); diff --git a/t/httpd-unix.t b/t/httpd-unix.t index 95f589ad..0b620bd6 100644 --- a/t/httpd-unix.t +++ b/t/httpd-unix.t @@ -7,7 +7,7 @@ use PublicInbox::TestCommon; use Errno qw(EADDRINUSE); use Cwd qw(abs_path); use Carp qw(croak); -use Fcntl qw(FD_CLOEXEC F_SETFD); +use autodie qw(close); require_mods(qw(Plack::Util Plack::Builder HTTP::Date HTTP::Status)); use IO::Socket::UNIX; use POSIX qw(mkfifo); @@ -125,11 +125,10 @@ SKIP: { }; for my $w (qw(-W0 -W1)) { - pipe(my ($p0, $p1)) or xbail "pipe: $!"; - fcntl($p1, F_SETFD, 0) or xbail "fcntl: $!"; # clear FD_CLOEXEC + my ($p0, $p1) = quit_waiter_pipe; # wait for daemonization $spawn_httpd->("-l$unix", '-D', '-P', $pid_file, $w); - close $p1 or xbail "close: $!"; + close $p1; $td->join; is($?, 0, "daemonized $w process"); check_sock($unix); @@ -137,13 +136,9 @@ SKIP: { my $pid = $read_pid->($pid_file); no_pollerfd($pid) if $w eq '-W1'; is(kill('TERM', $pid), 1, "signaled daemonized $w process"); - vec(my $rvec = '', fileno($p0), 1) = 1; delete $td->{-extra}; # drop tail(1) process - is(select($rvec, undef, undef, 1), 1, 'timeout for pipe HUP'); - is(my $undef = <$p0>, undef, 'process closed pipe writer at exit'); + wait_for_eof($p0, "httpd $w quit pipe"); ok(!-e $pid_file, "$w pid file unlinked at exit"); - delay_until(sub { !kill(0, $pid) }, - "daemonized $w really not running"); } my $httpd = abs_path('blib/script/public-inbox-httpd'); @@ -152,11 +147,9 @@ SKIP: { my @args = ("-l$unix", '-D', '-P', $pid_file, -1, $out, -2, $err); if ('USR2 upgrades with workers') { - pipe(my ($p0, $p1)) or xbail "pipe: $!"; - fcntl($p1, F_SETFD, 0) or xbail "fcntl: $!"; # clear FD_CLOEXEC - + my ($p0, $p1) = quit_waiter_pipe; $td = start_script([$httpd, @args, $psgi], undef, $opt); - close($p1) or xbail "close: $!"; + close $p1; $td->join; is($?, 0, "daemonized process again"); check_sock($unix); @@ -211,19 +204,14 @@ SKIP: { check_sock($unix); kill('QUIT', $new_pid) or die "QUIT failed: $!"; - vec(my $rvec = '', fileno($p0), 1) = 1; - is(select($rvec, undef, undef, 1), 1, 'timeout for pipe HUP'); - is(my $u = <$p0>, undef, 'process closed pipe writer at exit'); - + wait_for_eof($p0, 'new process'); ok(!-f $pid_file, 'PID file is gone'); - delay_until(sub { !kill(0, $new_pid) }, 'new PID really died'); } if ('try USR2 without workers (-W0)') { - pipe(my ($p0, $p1)) or xbail "pipe: $!"; - fcntl($p1, F_SETFD, 0) or xbail "fcntl: $!"; # clear FD_CLOEXEC + my ($p0, $p1) = quit_waiter_pipe; $td = start_script([$httpd, @args, '-W0', $psgi], undef, $opt); - close $p1 or xbail "close: $!"; + close $p1; $td->join; is($?, 0, 'daemonized w/o workers'); $register_exit_fifo->($unix, $f1); @@ -238,11 +226,8 @@ SKIP: { $pid = $read_pid->($pid_file); kill('QUIT', $pid) or xbail "USR2 failed: $!"; - vec(my $rvec = '', fileno($p0), 1) = 1; - is(select($rvec, undef, undef, 1), 1, 'timeout for pipe HUP'); - is(my $u = <$p0>, undef, 'process closed pipe writer at exit'); + wait_for_eof($p0, '-W0 USR2 test pipe'); ok(!-f $pid_file, 'PID file is gone'); - delay_until(sub { !kill(0, $pid) }, '-W0 daemon is gone'); } } |