File Coverage

lib/Ubic/Service/SimpleDaemon.pm
Criterion Covered Total %
statement 73 96 76.0
branch 22 42 52.3
condition n/a
subroutine 18 21 85.7
pod 11 11 100.0
total 124 170 72.9


line stmt bran cond sub pod time code
1             package Ubic::Service::SimpleDaemon;
2             $Ubic::Service::SimpleDaemon::VERSION = '1.60';
3 20     20   2819 use strict;
  20         24  
  20         513  
4 20     20   64 use warnings;
  20         24  
  20         590  
5              
6             # ABSTRACT: service module for daemonizing any binary
7              
8              
9 20     20   67 use parent qw(Ubic::Service::Skeleton);
  20         25  
  20         113  
10              
11 20     20   5834 use Ubic::Daemon qw(start_daemon stop_daemon check_daemon);
  20         31  
  20         116  
12 20     20   88 use Ubic::Result qw(result);
  20         25  
  20         825  
13 20     20   71 use Ubic::Settings;
  20         20  
  20         377  
14              
15 20     20   65 use Params::Validate qw(:all);
  20         21  
  20         19520  
16              
17             # Beware - this code will ignore any overrides if you're using custom Ubic->new(...) objects
18             our $PID_DIR;
19              
20             sub _pid_dir {
21 140 100   140   1110 return $PID_DIR if defined $PID_DIR;
22 11 50       59 if ($ENV{UBIC_DAEMON_PID_DIR}) {
23 0         0 warn "UBIC_DAEMON_PID_DIR env variable is deprecated, use Ubic->set_data_dir or configs instead (see Ubic::Settings for details)";
24 0         0 $PID_DIR = $ENV{UBIC_DAEMON_PID_DIR};
25             }
26             else {
27 11         46 $PID_DIR = Ubic::Settings->data_dir."/simple-daemon/pid";
28             }
29 11         110 return $PID_DIR;
30             }
31              
32             sub _send_signal {
33 8     8   25 my ($self, $signal) = @_;
34              
35 8         29 my $daemon = check_daemon($self->pidfile);
36 8 100       39 unless ($daemon) {
37 3         9 return result('not running');
38             }
39              
40 5         28 my $pid = $daemon->pid;
41 5         114 kill $signal => $pid;
42              
43 5         21 my $guardian_pid = $daemon->guardian_pid;
44 5         46 kill HUP => $guardian_pid;
45              
46 5         47 return result('reloaded', "sent $self->{reload_signal} to $pid, sent HUP to $guardian_pid");
47             }
48              
49             sub new {
50 39     39 1 9614 my $class = shift;
51 39         2493 my $params = validate(@_, {
52             bin => { type => SCALAR | ARRAYREF },
53             user => { type => SCALAR, optional => 1 },
54             group => { type => SCALAR | ARRAYREF, optional => 1 },
55             daemon_user => { type => SCALAR, optional => 1 },
56             daemon_group => { type => SCALAR | ARRAYREF, optional => 1 },
57             name => { type => SCALAR, optional => 1 },
58             pidfile => { type => SCALAR, optional => 1 },
59             stdout => { type => SCALAR, optional => 1 },
60             stderr => { type => SCALAR, optional => 1 },
61             ubic_log => { type => SCALAR, optional => 1 },
62             proxy_logs => { type => BOOLEAN, optional => 1 },
63             cwd => { type => SCALAR, optional => 1 },
64             env => { type => HASHREF, optional => 1 },
65             reload_signal => { type => SCALAR, optional => 1 },
66             term_timeout => { type => SCALAR, optional => 1, regex => qr/^\d+$/ },
67             stop_timeout => { type => SCALAR, optional => 1, regex => qr/^\d+$/ },
68             ulimit => { type => HASHREF, optional => 1 },
69             auto_start => { type => BOOLEAN, default => 0 },
70             kill_child_signal => { type => SCALAR, default => -15, optional => 1 },
71             });
72              
73 39 50       538 if ($params->{ulimit}) {
74             # load BSD::Resource lazily, but fail fast if we're asked for it
75 0         0 eval "require BSD::Resource";
76 0 0       0 if ($@) {
77 0         0 die "BSD::Resource is not installed";
78             }
79 0 0       0 if (BSD::Resource->VERSION < 1.29) {
80             # 1.29 supports string names for resources
81 0         0 die "BSD::Resource >= 1.29 required";
82             }
83             }
84              
85 39         343 return bless {%$params} => $class;
86             }
87              
88             sub pidfile {
89 140     140 1 252 my ($self) = @_;
90 140 50       503 return $self->{pidfile} if exists($self->{pidfile});
91 140 50       689 my $name = $self->full_name or die "Can't start nameless SimpleDaemon";
92 140         451 return _pid_dir."/$name";
93             }
94              
95             sub start_impl {
96 21     21 1 27 my ($self) = @_;
97              
98             my $start_params = {
99             pidfile => $self->pidfile,
100             bin => $self->{bin},
101 21         51 };
102 21         67 for (qw/ env cwd stdout stderr ubic_log proxy_logs term_timeout /) {
103 147 100       266 $start_params->{$_} = $self->{$_} if defined $self->{$_};
104             }
105 21 100       55 if ($self->{reload_signal}) {
106 5         10 $start_params->{proxy_logs} = 1;
107             }
108 21 50       58 if ($self->{kill_child_signal}) {
109 21         44 $start_params->{kill_child_signal} = $self->{kill_child_signal};
110             }
111 21 50       62 if (defined $self->{daemon_user}) {
112             $start_params->{credentials} = Ubic::Credentials->new(
113             user => $self->{daemon_user},
114             group => $self->{daemon_group},
115 0         0 );
116             }
117 21 50       55 if (defined $self->{ulimit}) {
118             $start_params->{start_hook} = sub {
119 0     0   0 for my $name (keys %{$self->{ulimit}}) {
  0         0  
120 0         0 my $value = $self->{ulimit}{$name};
121 0         0 my $result = BSD::Resource::setrlimit($name, $value, $value);
122 0 0       0 unless ($result) {
123 0         0 die "Failed to set $name=$value ulimit";
124             }
125             }
126 0         0 };
127             }
128 21         98 start_daemon($start_params);
129             }
130              
131             sub user {
132 60     60 1 68 my $self = shift;
133 60 50       142 return $self->{user} if defined $self->{user};
134 60         238 return $self->SUPER::user();
135             }
136              
137             sub group {
138 60     60 1 65 my $self = shift;
139 60         65 my $groups = $self->{group};
140 60 50       207 return $self->SUPER::group() if not defined $groups;
141 0 0       0 return @$groups if ref $groups eq 'ARRAY';
142 0         0 return $groups;
143             }
144              
145             sub stop_impl {
146 15     15 1 21 my ($self) = @_;
147 15         23 my $options = {};
148 15 50       99 $options->{timeout} = $self->{stop_timeout} if $self->{stop_timeout};
149 15         41 stop_daemon($self->pidfile,$options);
150             }
151              
152             sub status_impl {
153 96     96 1 234 my ($self) = @_;
154 96 100       340 if (my $daemon = check_daemon($self->pidfile)) {
155 44         158 return result('running', "pid ".$daemon->pid);
156             }
157             else {
158 52         195 return result('not running');
159             }
160             }
161              
162             sub reload {
163 11     11 1 4002372 my $self = shift;
164 11 100       69 unless (defined $self->{reload_signal}) {
165 3         24 return result('unknown', 'not implemented');
166             }
167 8         45 return $self->_send_signal($self->{reload_signal});
168             }
169              
170             sub auto_start {
171 4     4 1 6 my $self = shift;
172 4         31 return $self->{auto_start};
173             }
174              
175              
176             our %SIGNALS = (
177             sigusr1 => 'SIGUSR1',
178             sigusr2 => 'SIGUSR2',
179             );
180              
181             sub custom_commands {
182 0     0 1   my ($self) = @_;
183 0           return keys %SIGNALS;
184             }
185              
186             sub do_custom_command {
187 0     0 1   my ($self, $command) = @_;
188 0 0         unless (defined $SIGNALS{$command}) {
189 0           return result('unknown', 'not implemented');
190             }
191              
192 0           return $self->_send_signal($SIGNALS{$command});
193             }
194              
195              
196             1;
197              
198             __END__