unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / mirror / code / Atom feed
blob 87231372e3e9c2e284fe271813f0625e6a3cdd19 3354 bytes (raw)
name: t/active-unix-socket.t 	 # note: path name is non-authoritative(*)

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
 
#!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 IO::Socket::UNIX;
use autodie;
no autodie 'kill';
my %to_kill;
END { kill('TERM', values(%to_kill)) if keys %to_kill }
my $u1 = "$tmpdir/u1.sock";
my $u2 = "$tmpdir/u2.sock";
{
	open my $fh, '>', "$tmpdir/u1.conf.rb";
	print $fh <<EOM;
pid "$tmpdir/u.pid"
listen "$u1"
stderr_path "$tmpdir/err.log"
EOM
	close $fh;

	open $fh, '>', "$tmpdir/u2.conf.rb";
	print $fh <<EOM;
pid "$tmpdir/u.pid"
listen "$u2"
stderr_path "$tmpdir/err2.log"
EOM
	close $fh;

	open $fh, '>', "$tmpdir/u3.conf.rb";
	print $fh <<EOM;
pid "$tmpdir/u3.pid"
listen "$u1"
stderr_path "$tmpdir/err3.log"
EOM
	close $fh;
}

my @uarg = qw(-D -E none t/integration.ru);

# this pipe will be used to notify us when all daemons die:
pipe(my $p0, my $p1);
fcntl($p1, POSIX::F_SETFD, 0);

# start the first instance
unicorn('-c', "$tmpdir/u1.conf.rb", @uarg)->join;
is($?, 0, 'daemonized 1st process');
chomp($to_kill{u1} = slurp("$tmpdir/u.pid"));
like($to_kill{u1}, qr/\A\d+\z/s, 'read pid file');

chomp(my $worker_pid = readline(unix_start($u1, 'GET /pid')));
like($worker_pid, qr/\A\d+\z/s, 'captured worker pid');
ok(kill(0, $worker_pid), 'worker is kill-able');


# 2nd process conflicts on PID
unicorn('-c', "$tmpdir/u2.conf.rb", @uarg)->join;
isnt($?, 0, 'conflicting PID file fails to start');

chomp(my $pidf = slurp("$tmpdir/u.pid"));
is($pidf, $to_kill{u1}, 'pid file contents unchanged after start failure');

chomp(my $pid2 = readline(unix_start($u1, 'GET /pid')));
is($worker_pid, $pid2, 'worker PID unchanged');


# 3rd process conflicts on socket
unicorn('-c', "$tmpdir/u3.conf.rb", @uarg)->join;
isnt($?, 0, 'conflicting UNIX socket fails to start');

chomp($pid2 = readline(unix_start($u1, 'GET /pid')));
is($worker_pid, $pid2, 'worker PID still unchanged');

chomp($pidf = slurp("$tmpdir/u.pid"));
is($pidf, $to_kill{u1}, 'pid file contents unchanged after 2nd start failure');

{ # teardown initial process via SIGKILL
	ok(kill('KILL', delete $to_kill{u1}), 'SIGKILL initial daemon');
	close $p1;
	vec(my $rvec = '', fileno($p0), 1) = 1;
	is(select($rvec, undef, undef, 5), 1, 'timeout for pipe HUP');
	is(my $undef = <$p0>, undef, 'process closed pipe writer at exit');
	ok(-f "$tmpdir/u.pid", 'pid file stayed after SIGKILL');
	ok(-S $u1, 'socket stayed after SIGKILL');
	is(IO::Socket::UNIX->new(Peer => $u1, Type => SOCK_STREAM), undef,
		'fail to connect to u1');
	ok(!kill(0, $worker_pid), 'worker gone after parent dies');
}

# restart the first instance
{
	pipe($p0, $p1);
	fcntl($p1, POSIX::F_SETFD, 0);
	unicorn('-c', "$tmpdir/u1.conf.rb", @uarg)->join;
	is($?, 0, 'daemonized 1st process');
	chomp($to_kill{u1} = slurp("$tmpdir/u.pid"));
	like($to_kill{u1}, qr/\A\d+\z/s, 'read pid file');

	chomp($pid2 = readline(unix_start($u1, 'GET /pid')));
	like($pid2, qr/\A\d+\z/, 'worker running');

	ok(kill('TERM', delete $to_kill{u1}), 'SIGTERM restarted daemon');
	close $p1;
	vec(my $rvec = '', fileno($p0), 1) = 1;
	is(select($rvec, undef, undef, 5), 1, 'timeout for pipe HUP');
	is(my $undef = <$p0>, undef, 'process closed pipe writer at exit');
	ok(!-f "$tmpdir/u.pid", 'pid file gone after SIGTERM');
	ok(-S $u1, 'socket stays after SIGTERM');
}

check_stderr;
done_testing;

debug log:

solving 8723137 ...
found 8723137 in https://yhbt.net/unicorn.git/

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://yhbt.net/unicorn.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).