move STDERR re-opening to a better place
[scpubgit/Tak-Daemon.git] / lib / Tak / Daemon / DaemonService.pm
1 package Tak::Daemon::DaemonService;
2
3 use POSIX;
4 use Log::Contextual ();
5 use Log::Contextual::SimpleLogger;
6 use Tak::Router;
7 use Moo;
8
9 with 'Tak::Role::Service';
10
11 has 'set_done_cb' => (is => 'rw');
12
13 has 'router' => (is => 'lazy');
14
15 sub _build_router { Tak::Router->new }
16
17 sub handle_daemonize {
18   my ($self) = @_;
19   fork and exit;
20   POSIX::setsid or die "Couldn't setsid: $!";
21   fork and exit;
22   return 'done';
23 }
24
25 sub handle_become_successor {
26   my ($self) = @_;
27   my $done;
28   $self->set_done_cb(sub { $done = 1 });
29   # because this is funnier than "no warnings 'once'". Also because
30   # I don't have to stop and think "what else is in this lexical scope?"
31   $Tak::STDIOSetup::Next = $Tak::STDIOSetup::Next = sub {
32
33     # have to do this here because when we're being set up stderr may
34     # be redirected (e.g. because we're in an ->do under a repl) - and
35     # plus it leaves logging running until the last possible minute,
36     # which is almost certainly a win anyway.
37     close STDERR;
38     open STDERR, '>', '/dev/null' or die "Couldn't re-open stderr: $!";
39     Log::Contextual::set_logger( # there's no NullLogger? I thought I wrote one
40       Log::Contextual::SimpleLogger->new({ levels => [] })
41     );
42
43     my $x = $self; # close over while evading void context warnings
44     $0 = 'tak-daemon-node';
45     Tak->loop_until($done);
46   };
47   return 'done';
48 }
49
50 sub handle_shutdown {
51   my ($self) = @_;
52   $self->set_done_cb->();
53   return 'done';
54 }
55
56 sub start_router_request {
57   shift->router->start_request(@_);
58 }
59
60 sub receive_router {
61   shift->router->receive(@_);
62 }
63
64 1;