From 81a9a43fb858d197ffd1532d73f9f22739f940ff Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 24 Nov 2019 00:22:28 +0000 Subject: daemon: use sigprocmask to block signals at startup `$SIG{FOO} = "IGNORE"' will cause the daemon to miss signals entirely. Instead, we can use sigprocmask to block signal delivery until we have our signal handlers setup. This closes a race where a PID file can be written for an init script and a signal to be dropped via "IGNORE". --- lib/PublicInbox/Daemon.pm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/PublicInbox/Daemon.pm b/lib/PublicInbox/Daemon.pm index b3743f5c..e830a98f 100644 --- a/lib/PublicInbox/Daemon.pm +++ b/lib/PublicInbox/Daemon.pm @@ -8,7 +8,7 @@ use warnings; use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/; use IO::Handle; use IO::Socket; -use POSIX qw(WNOHANG); +use POSIX qw(WNOHANG :signal_h); use Socket qw(IPPROTO_TCP SOL_SOCKET); sub SO_ACCEPTFILTER () { 0x1000 } use Cwd qw/abs_path/; @@ -19,7 +19,7 @@ require PublicInbox::EvCleanup; require PublicInbox::Listener; require PublicInbox::ParentPipe; my @CMD; -my $set_user; +my ($set_user, $oldset); my (@cfg_listen, $stdout, $stderr, $group, $user, $pid_file, $daemonize); my $worker_processes = 1; my @listeners; @@ -76,9 +76,11 @@ sub accept_tls_opt ($) { sub daemon_prepare ($) { my ($default_listen) = @_; + $oldset = POSIX::SigSet->new(); + my $newset = POSIX::SigSet->new(); + $newset->fillset or die "fillset: $!"; + sigprocmask(SIG_SETMASK, $newset, $oldset) or die "sigprocmask: $!"; @CMD = ($0, @ARGV); - $SIG{HUP} = $SIG{USR1} = $SIG{USR2} = $SIG{PIPE} = - $SIG{TTIN} = $SIG{TTOU} = $SIG{WINCH} = 'IGNORE'; my %opts = ( 'l|listen=s' => \@cfg_listen, '1|stdout=s' => \$stdout, @@ -482,6 +484,7 @@ sub master_loop { syswrite($w, '.'); }; } + sigprocmask(SIG_SETMASK, $oldset) or die "sigprocmask: $!"; reopen_logs(); # main loop my $quit = 0; @@ -616,6 +619,7 @@ sub daemon_loop ($$$$) { # this calls epoll_create: PublicInbox::Listener->new($_, $tls_cb || $post_accept) } @listeners; + sigprocmask(SIG_SETMASK, $oldset) or die "sigprocmask: $!"; PublicInbox::DS->EventLoop; $parent_pipe = undef; } -- cgit v1.2.3-24-ge0c7