X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FDaemon.pm;h=43ef2691341a7cd46924541a103c27b8b1e5c79b;hb=98407632803aa6441e7882c713d55a399a25b710;hp=842ff1ccfd3424b677ca66eca8cd41c740fc29fc;hpb=8d9f0928dba4a9ccf5c078660cc9b27048a6b453;p=public-inbox.git diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index 842ff1cc..43ef2691 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2015-2019 all contributors +# Copyright (C) 2015-2020 all contributors # License: AGPL-3.0+ # contains common daemon code for the nntpd and httpd servers. # This may be used for read-only IMAP server if we decide to implement it. @@ -6,7 +6,7 @@ package PublicInbox::Daemon; use strict; use warnings; use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/; -use IO::Handle; +use IO::Handle; # ->autoflush use IO::Socket; use POSIX qw(WNOHANG :signal_h); use Socket qw(IPPROTO_TCP SOL_SOCKET); @@ -462,23 +462,27 @@ sub unlink_pid_file_safe_ish ($$) { } } +sub master_quit ($) { + exit unless @listeners; + @listeners = (); + kill_workers($_[0]); +} + sub master_loop { pipe(my ($p0, $p1)) or die "failed to create parent-pipe: $!"; # 1031: F_SETPIPE_SZ, 4096: page size fcntl($p1, 1031, 4096) if $^O eq 'linux'; my $set_workers = $worker_processes; reopen_logs(); - my $quit = 0; my $ignore_winch; - my $quit_cb = sub { exit if $quit++; kill_workers($_[0]) }; my $sig = { USR1 => sub { reopen_logs(); kill_workers($_[0]); }, USR2 => \&upgrade, - QUIT => $quit_cb, - INT => $quit_cb, - TERM => $quit_cb, + QUIT => \&master_quit, + INT => \&master_quit, + TERM => \&master_quit, WINCH => sub { - return if $ignore_winch; + return if $ignore_winch || !@listeners; if (-t STDIN || -t STDOUT || -t STDERR) { $ignore_winch = 1; warn < sub { + return unless @listeners; $worker_processes = $set_workers; kill_workers($_[0]); }, TTIN => sub { + return unless @listeners; if ($set_workers > $worker_processes) { ++$worker_processes; } else { @@ -509,7 +515,7 @@ EOF sig_setmask($oldset) if !$sigfd; while (1) { # main loop my $n = scalar keys %pids; - if ($quit) { + unless (@listeners) { exit if $n == 0; $set_workers = $worker_processes = $n = 0; } @@ -560,11 +566,12 @@ sub defer_accept ($$) { my ($s, $af_name) = @_; return unless defined $af_name; if ($^O eq 'linux') { - my $x = getsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT()); + my $TCP_DEFER_ACCEPT = 9; # Socket::TCP_DEFER_ACCEPT is in 5.14+ + my $x = getsockopt($s, IPPROTO_TCP, $TCP_DEFER_ACCEPT); return unless defined $x; # may be Unix socket my $sec = unpack('i', $x); return if $sec > 0; # systemd users may set a higher value - setsockopt($s, IPPROTO_TCP, Socket::TCP_DEFER_ACCEPT(), 1); + setsockopt($s, IPPROTO_TCP, $TCP_DEFER_ACCEPT, 1); } elsif ($^O eq 'freebsd') { my $x = getsockopt($s, SOL_SOCKET, SO_ACCEPTFILTER); return if defined $x; # don't change if set @@ -595,11 +602,10 @@ sub daemon_loop ($$$$) { WINCH => 'IGNORE', CHLD => \&PublicInbox::DS::enqueue_reap, }; - my $parent_pipe; if ($worker_processes > 0) { $refresh->(); # preload by default my $fh = master_loop(); # returns if in child process - $parent_pipe = PublicInbox::ParentPipe->new($fh, *worker_quit); + PublicInbox::ParentPipe->new($fh, \&worker_quit); } else { reopen_logs(); $set_user->() if $set_user; @@ -631,6 +637,7 @@ sub daemon_loop ($$$$) { sub run ($$$;$) { my ($default, $refresh, $post_accept, $nntpd) = @_; + local $SIG{PIPE} = 'IGNORE'; daemon_prepare($default); my $af_default = $default =~ /:8080\z/ ? 'httpready' : undef; my $for_destroy = daemonize();