File Coverage

lib/Ubic/Service/SimpleDaemon.pm
Criterion Covered Total %
statement 71 94 75.5
branch 21 40 52.5
condition n/a
subroutine 18 21 85.7
pod 11 11 100.0
total 121 166 72.8


line stmt bran cond sub pod time code
1             package Ubic::Service::SimpleDaemon;
2             $Ubic::Service::SimpleDaemon::VERSION = '1.58_01'; # TRIAL
3 22     22   4333 use strict;
  22         44  
  22         1381  
4 22     22   158 use warnings;
  22         38  
  22         959  
5              
6             # ABSTRACT: service module for daemonizing any binary
7              
8              
9 22     22   104 use parent qw(Ubic::Service::Skeleton);
  22         37  
  22         190  
10              
11 22     22   9224 use Ubic::Daemon qw(start_daemon stop_daemon check_daemon);
  22         56  
  22         197  
12 22     22   131 use Ubic::Result qw(result);
  22         35  
  22         1155  
13 22     22   99 use Ubic::Settings;
  22         32  
  22         518  
14              
15 22     22   96 use Params::Validate qw(:all);
  22         29  
  22         26531  
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 197 100   197   1840 return $PID_DIR if defined $PID_DIR;
22 14 50       83 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 14         95 $PID_DIR = Ubic::Settings->data_dir."/simple-daemon/pid";
28             }
29 14         170 return $PID_DIR;
30             }
31              
32             sub _send_signal {
33 11     11   31 my ($self, $signal) = @_;
34              
35 11         66 my $daemon = check_daemon($self->pidfile);
36 11 100       49 unless ($daemon) {
37 4         20 return result('not running');
38             }
39              
40 7         46 my $pid = $daemon->pid;
41 7         177 kill $signal => $pid;
42              
43 7         34 my $guardian_pid = $daemon->guardian_pid;
44 7         63 kill HUP => $guardian_pid;
45              
46 7         76 return result('reloaded', "sent $self->{reload_signal} to $pid, sent HUP to $guardian_pid");
47             }
48              
49             sub new {
50 52     52 1 31960 my $class = shift;
51 52         5104 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             });
71              
72 52 50       996 if ($params->{ulimit}) {
73             # load BSD::Resource lazily, but fail fast if we're asked for it
74 0         0 eval "require BSD::Resource";
75 0 0       0 if ($@) {
76 0         0 die "BSD::Resource is not installed";
77             }
78 0 0       0 if (BSD::Resource->VERSION < 1.29) {
79             # 1.29 supports string names for resources
80 0         0 die "BSD::Resource >= 1.29 required";
81             }
82             }
83              
84 52         588 return bless {%$params} => $class;
85             }
86              
87             sub pidfile {
88 197     197 1 309 my ($self) = @_;
89 197 50       916 return $self->{pidfile} if exists($self->{pidfile});
90 197 50       1350 my $name = $self->full_name or die "Can't start nameless SimpleDaemon";
91 197         759 return _pid_dir."/$name";
92             }
93              
94             sub start_impl {
95 30     30 1 52 my ($self) = @_;
96              
97             my $start_params = {
98             pidfile => $self->pidfile,
99             bin => $self->{bin},
100 30         109 };
101 30         103 for (qw/ env cwd stdout stderr ubic_log proxy_logs term_timeout /) {
102 210 100       492 $start_params->{$_} = $self->{$_} if defined $self->{$_};
103             }
104 30 100       100 if ($self->{reload_signal}) {
105 6         22 $start_params->{proxy_logs} = 1;
106             }
107 30 50       120 if (defined $self->{daemon_user}) {
108             $start_params->{credentials} = Ubic::Credentials->new(
109             user => $self->{daemon_user},
110             group => $self->{daemon_group},
111 0         0 );
112             }
113 30 50       127 if (defined $self->{ulimit}) {
114             $start_params->{start_hook} = sub {
115 0     0   0 for my $name (keys %{$self->{ulimit}}) {
  0         0  
116 0         0 my $value = $self->{ulimit}{$name};
117 0         0 my $result = BSD::Resource::setrlimit($name, $value, $value);
118 0 0       0 unless ($result) {
119 0         0 die "Failed to set $name=$value ulimit";
120             }
121             }
122 0         0 };
123             }
124 30         203 start_daemon($start_params);
125             }
126              
127             sub user {
128 68     68 1 102 my $self = shift;
129 68 50       251 return $self->{user} if defined $self->{user};
130 68         314 return $self->SUPER::user();
131             }
132              
133             sub group {
134 68     68 1 94 my $self = shift;
135 68         104 my $groups = $self->{group};
136 68 50       298 return $self->SUPER::group() if not defined $groups;
137 0 0       0 return @$groups if ref $groups eq 'ARRAY';
138 0         0 return $groups;
139             }
140              
141             sub stop_impl {
142 21     21 1 39 my ($self) = @_;
143 21         41 my $options = {};
144 21 50       91 $options->{timeout} = $self->{stop_timeout} if $self->{stop_timeout};
145 21         72 stop_daemon($self->pidfile,$options);
146             }
147              
148             sub status_impl {
149 135     135 1 401 my ($self) = @_;
150 135 100       700 if (my $daemon = check_daemon($self->pidfile)) {
151 61         271 return result('running', "pid ".$daemon->pid);
152             }
153             else {
154 74         565 return result('not running');
155             }
156             }
157              
158             sub reload {
159 15     15 1 5003490 my $self = shift;
160 15 100       87 unless (defined $self->{reload_signal}) {
161 4         36 return result('unknown', 'not implemented');
162             }
163 11         57 return $self->_send_signal($self->{reload_signal});
164             }
165              
166             sub auto_start {
167 6     6 1 13 my $self = shift;
168 6         56 return $self->{auto_start};
169             }
170              
171              
172             our %SIGNALS = (
173             sigusr1 => 'SIGUSR1',
174             sigusr2 => 'SIGUSR2',
175             );
176              
177             sub custom_commands {
178 0     0 1   my ($self) = @_;
179 0           return keys %SIGNALS;
180             }
181              
182             sub do_custom_command {
183 0     0 1   my ($self, $command) = @_;
184 0 0         unless (defined $SIGNALS{$command}) {
185 0           return result('unknown', 'not implemented');
186             }
187              
188 0           return $self->_send_signal($SIGNALS{$command});
189             }
190              
191              
192             1;
193              
194             __END__