| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#+############################################################################## |
|
2
|
|
|
|
|
|
|
# # |
|
3
|
|
|
|
|
|
|
# File: No/Worries/PidFile.pm # |
|
4
|
|
|
|
|
|
|
# # |
|
5
|
|
|
|
|
|
|
# Description: pid file handling without worries # |
|
6
|
|
|
|
|
|
|
# # |
|
7
|
|
|
|
|
|
|
#-############################################################################## |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# |
|
10
|
|
|
|
|
|
|
# module definition |
|
11
|
|
|
|
|
|
|
# |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
package No::Worries::PidFile; |
|
14
|
1
|
|
|
1
|
|
563
|
use strict; |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
34
|
|
|
15
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
76
|
|
|
16
|
|
|
|
|
|
|
our $VERSION = "1.7"; |
|
17
|
|
|
|
|
|
|
our $REVISION = sprintf("%d.%02d", q$Revision: 1.21 $ =~ /(\d+)\.(\d+)/); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# |
|
20
|
|
|
|
|
|
|
# used modules |
|
21
|
|
|
|
|
|
|
# |
|
22
|
|
|
|
|
|
|
|
|
23
|
1
|
|
|
1
|
|
5
|
use Fcntl qw(:DEFAULT :flock :seek); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
355
|
|
|
24
|
1
|
|
|
1
|
|
7
|
use No::Worries qw($_IntegerRegexp $_NumberRegexp); |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
7
|
|
|
25
|
1
|
|
|
1
|
|
6
|
use No::Worries::Die qw(dief); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
8
|
|
|
26
|
1
|
|
|
1
|
|
7
|
use No::Worries::Export qw(export_control); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
6
|
|
|
27
|
1
|
|
|
1
|
|
7
|
use No::Worries::Proc qw(proc_terminate); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
6
|
|
|
28
|
1
|
|
|
1
|
|
529
|
use No::Worries::Stat qw(ST_MTIME); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
7
|
|
|
29
|
1
|
|
|
1
|
|
7
|
use Params::Validate qw(validate :types); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
131
|
|
|
30
|
1
|
|
|
1
|
|
7
|
use POSIX qw(:errno_h); |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
10
|
|
|
31
|
1
|
|
|
1
|
|
337
|
use Time::HiRes qw(); |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
2510
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
# |
|
34
|
|
|
|
|
|
|
# safely read something from an open file |
|
35
|
|
|
|
|
|
|
# |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub _read ($$;$) { |
|
38
|
2
|
|
|
2
|
|
5
|
my($path, $fh, $noclose) = @_; |
|
39
|
2
|
|
|
|
|
4
|
my($data, $done); |
|
40
|
|
|
|
|
|
|
|
|
41
|
2
|
50
|
|
|
|
23
|
flock($fh, LOCK_EX) |
|
42
|
|
|
|
|
|
|
or dief("cannot flock(%s, LOCK_EX): %s", $path, $!); |
|
43
|
2
|
50
|
|
|
|
15
|
sysseek($fh, 0, SEEK_SET) |
|
44
|
|
|
|
|
|
|
or dief("cannot sysseek(%s, 0, SEEK_SET): %s", $path, $!); |
|
45
|
2
|
|
|
|
|
6
|
$data = ""; |
|
46
|
2
|
|
|
|
|
4
|
$done = -1; |
|
47
|
2
|
|
|
|
|
7
|
while ($done) { |
|
48
|
4
|
|
|
|
|
34
|
$done = sysread($fh, $data, 16, length($data)); |
|
49
|
4
|
50
|
|
|
|
17
|
dief("cannot sysread(%s, %d): %s", $path, 16, $!) |
|
50
|
|
|
|
|
|
|
unless defined($done); |
|
51
|
|
|
|
|
|
|
} |
|
52
|
2
|
50
|
|
|
|
6
|
if ($noclose) { |
|
53
|
0
|
0
|
|
|
|
0
|
flock($fh, LOCK_UN) |
|
54
|
|
|
|
|
|
|
or dief("cannot flock(%s, LOCK_UN): %s", $path, $!); |
|
55
|
|
|
|
|
|
|
} else { |
|
56
|
2
|
50
|
|
|
|
25
|
close($fh) |
|
57
|
|
|
|
|
|
|
or dief("cannot close(%s): %s", $path, $!); |
|
58
|
|
|
|
|
|
|
} |
|
59
|
2
|
|
|
|
|
8
|
return($data); |
|
60
|
|
|
|
|
|
|
} |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
# |
|
63
|
|
|
|
|
|
|
# safely write something to an open file |
|
64
|
|
|
|
|
|
|
# |
|
65
|
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub _write ($$$) { |
|
67
|
1
|
|
|
1
|
|
4
|
my($path, $fh, $data) = @_; |
|
68
|
1
|
|
|
|
|
2
|
my($length, $offset, $done); |
|
69
|
|
|
|
|
|
|
|
|
70
|
1
|
50
|
|
|
|
14
|
flock($fh, LOCK_EX) |
|
71
|
|
|
|
|
|
|
or dief("cannot flock(%s, LOCK_EX): %s", $path, $!); |
|
72
|
1
|
50
|
|
|
|
12
|
sysseek($fh, 0, SEEK_SET) |
|
73
|
|
|
|
|
|
|
or dief("cannot sysseek(%s, 0, SEEK_SET): %s", $path, $!); |
|
74
|
1
|
50
|
|
|
|
34
|
truncate($fh, 0) |
|
75
|
|
|
|
|
|
|
or dief("cannot truncate(%s, 0): %s", $path, $!); |
|
76
|
1
|
|
|
|
|
3
|
$length = length($data); |
|
77
|
1
|
|
|
|
|
2
|
$offset = 0; |
|
78
|
1
|
|
|
|
|
4
|
while ($length) { |
|
79
|
1
|
|
|
|
|
36
|
$done = syswrite($fh, $data, $length, $offset); |
|
80
|
1
|
50
|
|
|
|
7
|
dief("cannot syswrite(%s, %d): %s", $path, $length, $!) |
|
81
|
|
|
|
|
|
|
unless defined($done); |
|
82
|
1
|
|
|
|
|
2
|
$length -= $done; |
|
83
|
1
|
|
|
|
|
5
|
$offset += $done; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
1
|
50
|
|
|
|
802
|
close($fh) |
|
86
|
|
|
|
|
|
|
or dief("cannot close(%s): %s", $path, $!); |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# |
|
90
|
|
|
|
|
|
|
# check if a process is alive by killing it ;-) |
|
91
|
|
|
|
|
|
|
# |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub _alive ($) { |
|
94
|
1
|
|
|
1
|
|
3
|
my($pid) = @_; |
|
95
|
|
|
|
|
|
|
|
|
96
|
1
|
50
|
|
|
|
36
|
return(1) if kill(0, $pid); |
|
97
|
0
|
0
|
|
|
|
0
|
return(0) if $! == ESRCH; |
|
98
|
0
|
|
|
|
|
0
|
dief("cannot kill(0, %d): %s", $pid, $!); |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
# |
|
102
|
|
|
|
|
|
|
# kill a process |
|
103
|
|
|
|
|
|
|
# |
|
104
|
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub _kill ($$$%) { |
|
106
|
0
|
|
|
0
|
|
0
|
my($path, $fh, $pid, %option) = @_; |
|
107
|
0
|
|
|
|
|
0
|
my($maxtime); |
|
108
|
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# gently |
|
110
|
0
|
|
|
|
|
0
|
$option{callback}->("(pid $pid) is being told to quit..."); |
|
111
|
0
|
|
|
|
|
0
|
_write($path, $fh, "$pid\nquit\n"); |
|
112
|
0
|
|
|
|
|
0
|
$maxtime = Time::HiRes::time() + $option{linger}; |
|
113
|
0
|
|
|
|
|
0
|
while (1) { |
|
114
|
0
|
0
|
|
|
|
0
|
last unless _alive($pid); |
|
115
|
0
|
0
|
|
|
|
0
|
last if Time::HiRes::time() > $maxtime; |
|
116
|
0
|
|
|
|
|
0
|
Time::HiRes::sleep(0.1); |
|
117
|
|
|
|
|
|
|
} |
|
118
|
0
|
0
|
|
|
|
0
|
if (_alive($pid)) { |
|
119
|
|
|
|
|
|
|
# forcedly |
|
120
|
0
|
|
|
|
|
0
|
$option{callback}->("(pid $pid) is still running, killing it now..."); |
|
121
|
0
|
0
|
|
|
|
0
|
if ($option{kill}) { |
|
122
|
0
|
|
|
|
|
0
|
proc_terminate($pid, kill => $option{kill}); |
|
123
|
|
|
|
|
|
|
} else { |
|
124
|
0
|
|
|
|
|
0
|
proc_terminate($pid); |
|
125
|
|
|
|
|
|
|
} |
|
126
|
0
|
|
|
|
|
0
|
$option{callback}->("(pid $pid) has been successfully killed"); |
|
127
|
|
|
|
|
|
|
} else { |
|
128
|
0
|
|
|
|
|
0
|
$option{callback}->("does not seem to be running anymore"); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
} |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
# |
|
133
|
|
|
|
|
|
|
# check a process |
|
134
|
|
|
|
|
|
|
# |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub _status ($%) { |
|
137
|
2
|
|
|
2
|
|
7
|
my($path, %option) = @_; |
|
138
|
2
|
|
|
|
|
4
|
my($fh, @stat, $data, $pid, $status, $message, $lsb); |
|
139
|
|
|
|
|
|
|
|
|
140
|
2
|
|
|
|
|
4
|
$status = 0; |
|
141
|
2
|
100
|
|
|
|
68
|
unless (sysopen($fh, $path, O_RDWR)) { |
|
142
|
1
|
50
|
|
|
|
11
|
if ($! == ENOENT) { |
|
143
|
1
|
|
|
|
|
6
|
($message, $lsb) = |
|
144
|
|
|
|
|
|
|
("does not seem to be running (no pid file)", 3); |
|
145
|
1
|
|
|
|
|
11
|
goto done; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
0
|
|
|
|
|
0
|
dief("cannot sysopen(%s, O_RDWR): %s", $path, $!); |
|
148
|
|
|
|
|
|
|
} |
|
149
|
1
|
50
|
|
|
|
16
|
@stat = stat($fh) |
|
150
|
|
|
|
|
|
|
or dief("cannot stat(%s): %s", $path, $!); |
|
151
|
1
|
|
|
|
|
7
|
$data = _read($path, $fh); |
|
152
|
1
|
50
|
|
|
|
5
|
if ($data eq "") { |
|
153
|
|
|
|
|
|
|
# this can happen in pf_set(), between open() and lock() |
|
154
|
0
|
|
|
|
|
0
|
($message, $lsb) = |
|
155
|
|
|
|
|
|
|
("does not seem to be running yet (empty pid file)", 4); |
|
156
|
0
|
|
|
|
|
0
|
goto done; |
|
157
|
|
|
|
|
|
|
} |
|
158
|
1
|
50
|
|
|
|
10
|
if ($data =~ /^(\d+)(\s+([a-z]+))?\s*$/s) { |
|
159
|
1
|
|
|
|
|
4
|
$pid = $1; |
|
160
|
|
|
|
|
|
|
} else { |
|
161
|
0
|
|
|
|
|
0
|
dief("unexpected pid file contents in %s: %s", $path, $data); |
|
162
|
|
|
|
|
|
|
} |
|
163
|
1
|
50
|
|
|
|
4
|
unless (_alive($pid)) { |
|
164
|
0
|
|
|
|
|
0
|
($message, $lsb) = |
|
165
|
|
|
|
|
|
|
("(pid $pid) does not seem to be running anymore", 1); |
|
166
|
0
|
|
|
|
|
0
|
goto done; |
|
167
|
|
|
|
|
|
|
} |
|
168
|
1
|
|
|
|
|
51
|
$data = localtime($stat[ST_MTIME]); |
|
169
|
1
|
50
|
33
|
|
|
6
|
if ($option{freshness} and |
|
170
|
|
|
|
|
|
|
$stat[ST_MTIME] < Time::HiRes::time() - $option{freshness}) { |
|
171
|
0
|
|
|
|
|
0
|
($message, $lsb) = |
|
172
|
|
|
|
|
|
|
("(pid $pid) does not seem to be running anymore since $data", 4); |
|
173
|
0
|
|
|
|
|
0
|
goto done; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
# so far so good ;-) |
|
176
|
1
|
|
|
|
|
6
|
($status, $message, $lsb) = (1, "(pid $pid) was active on $data", 0); |
|
177
|
2
|
|
|
|
|
13
|
done: |
|
178
|
|
|
|
|
|
|
return($status, $message, $lsb); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
# |
|
182
|
|
|
|
|
|
|
# set the pid file |
|
183
|
|
|
|
|
|
|
# |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
my %pf_set_options = ( |
|
186
|
|
|
|
|
|
|
pid => { optional => 1, type => SCALAR, regex => $_IntegerRegexp }, |
|
187
|
|
|
|
|
|
|
); |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
sub pf_set ($@) { |
|
190
|
2
|
|
|
2
|
1
|
1119
|
my($path, %option, $fh); |
|
191
|
|
|
|
|
|
|
|
|
192
|
2
|
|
|
|
|
5
|
$path = shift(@_); |
|
193
|
2
|
50
|
|
|
|
53
|
%option = validate(@_, \%pf_set_options) if @_; |
|
194
|
2
|
|
33
|
|
|
17
|
$option{pid} ||= $$; |
|
195
|
2
|
100
|
|
|
|
104
|
sysopen($fh, $path, O_WRONLY|O_CREAT|O_EXCL) |
|
196
|
|
|
|
|
|
|
or dief("cannot sysopen(%s, O_WRONLY|O_CREAT|O_EXCL): %s", $path, $!); |
|
197
|
1
|
|
|
|
|
10
|
_write($path, $fh, "$option{pid}\n"); |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
# |
|
201
|
|
|
|
|
|
|
# check the pid file |
|
202
|
|
|
|
|
|
|
# |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
my %pf_check_options = ( |
|
205
|
|
|
|
|
|
|
pid => { optional => 1, type => SCALAR, regex => $_IntegerRegexp }, |
|
206
|
|
|
|
|
|
|
); |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub pf_check ($@) { |
|
209
|
2
|
|
|
2
|
1
|
2133
|
my($path, %option, $fh, $data, $pid, $action); |
|
210
|
|
|
|
|
|
|
|
|
211
|
2
|
|
|
|
|
4
|
$path = shift(@_); |
|
212
|
2
|
50
|
|
|
|
10
|
%option = validate(@_, \%pf_check_options) if @_; |
|
213
|
2
|
|
33
|
|
|
15
|
$option{pid} ||= $$; |
|
214
|
2
|
100
|
|
|
|
71
|
sysopen($fh, $path, O_RDWR) |
|
215
|
|
|
|
|
|
|
or dief("cannot sysopen(%s, O_RDWR): %s", $path, $!); |
|
216
|
1
|
|
|
|
|
7
|
$data = _read($path, $fh); |
|
217
|
1
|
50
|
|
|
|
11
|
if ($data =~ /^(\d+)\s*$/s) { |
|
|
|
0
|
|
|
|
|
|
|
218
|
1
|
|
|
|
|
5
|
($pid, $action) = ($1, ""); |
|
219
|
|
|
|
|
|
|
} elsif ($data =~ /^(\d+)\s+([a-z]+)\s*$/s) { |
|
220
|
0
|
|
|
|
|
0
|
($pid, $action) = ($1, $2); |
|
221
|
|
|
|
|
|
|
} else { |
|
222
|
0
|
|
|
|
|
0
|
dief("unexpected pid file contents in %s: %s", $path, $data) |
|
223
|
|
|
|
|
|
|
} |
|
224
|
|
|
|
|
|
|
dief("pid file %s has been taken over by pid %d!", $path, $pid) |
|
225
|
1
|
50
|
|
|
|
5
|
unless $pid == $option{pid}; |
|
226
|
1
|
|
|
|
|
5
|
return($action); |
|
227
|
|
|
|
|
|
|
} |
|
228
|
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
# |
|
230
|
|
|
|
|
|
|
# touch the pid file |
|
231
|
|
|
|
|
|
|
# |
|
232
|
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
sub pf_touch ($) { |
|
234
|
2
|
|
|
2
|
1
|
1231
|
my($path) = @_; |
|
235
|
2
|
|
|
|
|
4
|
my($now); |
|
236
|
|
|
|
|
|
|
|
|
237
|
2
|
|
|
|
|
5
|
$now = time(); |
|
238
|
2
|
100
|
|
|
|
48
|
utime($now, $now, $path) |
|
239
|
|
|
|
|
|
|
or dief("cannot utime(%d, %d, %s): %s", $now, $now, $path, $!); |
|
240
|
|
|
|
|
|
|
} |
|
241
|
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# |
|
243
|
|
|
|
|
|
|
# unset the pid file |
|
244
|
|
|
|
|
|
|
# |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
sub pf_unset ($) { |
|
247
|
2
|
|
|
2
|
1
|
1378
|
my($path) = @_; |
|
248
|
|
|
|
|
|
|
|
|
249
|
2
|
100
|
|
|
|
130
|
unless (unlink($path)) { |
|
250
|
1
|
50
|
|
|
|
10
|
return if $! == ENOENT; |
|
251
|
0
|
|
|
|
|
0
|
dief("cannot unlink(%s): %s", $path, $!); |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
# |
|
256
|
|
|
|
|
|
|
# use the pid file to find out the program status |
|
257
|
|
|
|
|
|
|
# |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
my %pf_status_options = ( |
|
260
|
|
|
|
|
|
|
freshness => { optional => 1, type => SCALAR, regex => $_NumberRegexp }, |
|
261
|
|
|
|
|
|
|
timeout => { optional => 1, type => SCALAR, regex => $_NumberRegexp }, |
|
262
|
|
|
|
|
|
|
); |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub pf_status ($@) { |
|
265
|
2
|
|
|
2
|
1
|
426
|
my($path, %option, $maxtime, $status, $message, $lsb); |
|
266
|
|
|
|
|
|
|
|
|
267
|
2
|
|
|
|
|
6
|
$path = shift(@_); |
|
268
|
2
|
50
|
|
|
|
8
|
%option = validate(@_, \%pf_status_options) if @_; |
|
269
|
2
|
50
|
|
|
|
8
|
if ($option{timeout}) { |
|
270
|
|
|
|
|
|
|
# check multiple times until success or timeout |
|
271
|
0
|
|
|
|
|
0
|
$maxtime = Time::HiRes::time() + $option{timeout}; |
|
272
|
0
|
|
|
|
|
0
|
while (1) { |
|
273
|
0
|
|
|
|
|
0
|
($status, $message, $lsb) = _status($path, %option); |
|
274
|
0
|
0
|
0
|
|
|
0
|
last if $status or Time::HiRes::time() > $maxtime; |
|
275
|
0
|
|
|
|
|
0
|
Time::HiRes::sleep(0.1); |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
} else { |
|
278
|
|
|
|
|
|
|
# check only once |
|
279
|
2
|
|
|
|
|
8
|
($status, $message, $lsb) = _status($path, %option); |
|
280
|
|
|
|
|
|
|
} |
|
281
|
2
|
50
|
|
|
|
17
|
return($status, $message, $lsb) if wantarray(); |
|
282
|
2
|
|
|
|
|
10
|
return($status); |
|
283
|
|
|
|
|
|
|
} |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
# |
|
286
|
|
|
|
|
|
|
# use the pid file to make the program quit |
|
287
|
|
|
|
|
|
|
# |
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
my %pf_quit_options = ( |
|
290
|
|
|
|
|
|
|
callback => { optional => 1, type => CODEREF }, |
|
291
|
|
|
|
|
|
|
linger => { optional => 1, type => SCALAR, regex => $_NumberRegexp }, |
|
292
|
|
|
|
|
|
|
kill => { optional => 1, type => SCALAR }, |
|
293
|
|
|
|
|
|
|
); |
|
294
|
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
sub pf_quit ($@) { |
|
296
|
1
|
|
|
1
|
1
|
741
|
my($path, %option, $fh, $data, $pid); |
|
297
|
|
|
|
|
|
|
|
|
298
|
1
|
|
|
|
|
3
|
$path = shift(@_); |
|
299
|
1
|
50
|
|
|
|
27
|
%option = validate(@_, \%pf_quit_options) if @_; |
|
300
|
1
|
|
50
|
0
|
|
7
|
$option{callback} ||= sub { printf("%s\n", $_[0]) }; |
|
|
0
|
|
|
|
|
0
|
|
|
301
|
1
|
|
50
|
|
|
7
|
$option{linger} ||= 5; |
|
302
|
1
|
50
|
|
|
|
24
|
unless (sysopen($fh, $path, O_RDWR)) { |
|
303
|
1
|
50
|
|
|
|
9
|
if ($! == ENOENT) { |
|
304
|
1
|
|
|
|
|
6
|
$option{callback}->("does not seem to be running (no pid file)"); |
|
305
|
1
|
|
|
|
|
7
|
return; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
0
|
|
|
|
|
0
|
dief("cannot sysopen(%s, O_RDWR): %s", $path, $!); |
|
308
|
|
|
|
|
|
|
} |
|
309
|
0
|
|
|
|
|
0
|
$data = _read($path, $fh, 1); |
|
310
|
0
|
0
|
|
|
|
0
|
if ($data eq "") { |
|
311
|
|
|
|
|
|
|
# this can happen while setting the pid file, between open and lock in pf_set() |
|
312
|
|
|
|
|
|
|
# but what can we do? we wait a bit, try again and complain if itis still empty |
|
313
|
0
|
|
|
|
|
0
|
sleep(1); |
|
314
|
0
|
|
|
|
|
0
|
$data = _read($path, $fh, 1); |
|
315
|
|
|
|
|
|
|
} |
|
316
|
0
|
0
|
|
|
|
0
|
if ($data =~ /^(\d+)(\s+([a-z]+))?\s*$/s) { |
|
317
|
0
|
|
|
|
|
0
|
$pid = $1; |
|
318
|
|
|
|
|
|
|
} else { |
|
319
|
0
|
|
|
|
|
0
|
dief("unexpected pid file contents in %s: %s", $path, $data); |
|
320
|
|
|
|
|
|
|
} |
|
321
|
0
|
|
|
|
|
0
|
_kill($path, $fh, $pid, %option); |
|
322
|
|
|
|
|
|
|
# in any case, we make sure that _this_ pid file does not exist anymore |
|
323
|
|
|
|
|
|
|
# we have to be extra careful to make sure it is the same pid file |
|
324
|
0
|
0
|
|
|
|
0
|
unless (sysopen($fh, $path, O_RDWR)) { |
|
325
|
0
|
0
|
|
|
|
0
|
return if $! == ENOENT; |
|
326
|
0
|
|
|
|
|
0
|
dief("cannot sysopen(%s, O_RDWR): %s", $path, $!); |
|
327
|
|
|
|
|
|
|
} |
|
328
|
0
|
|
|
|
|
0
|
$data = _read($path, $fh); |
|
329
|
0
|
0
|
|
|
|
0
|
return if $data eq ""; |
|
330
|
0
|
0
|
|
|
|
0
|
if ($data =~ /^(\d+)(\s+([a-z]+))?\s*$/s) { |
|
331
|
0
|
0
|
|
|
|
0
|
return unless $1 == $pid; |
|
332
|
|
|
|
|
|
|
} else { |
|
333
|
0
|
|
|
|
|
0
|
dief("unexpected pid file contents in %s: %s", $path, $data); |
|
334
|
|
|
|
|
|
|
} |
|
335
|
|
|
|
|
|
|
# same pid so assume same pid file... remove it |
|
336
|
0
|
|
|
|
|
0
|
$option{callback}->("removing stale pid file: $path"); |
|
337
|
0
|
0
|
|
|
|
0
|
unless (unlink($path)) { |
|
338
|
|
|
|
|
|
|
# take into account a potential race condition... |
|
339
|
0
|
0
|
|
|
|
0
|
dief("cannot unlink(%s): %s", $path, $!) unless $! == ENOENT; |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
} |
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
# |
|
344
|
|
|
|
|
|
|
# sleep for some time, taking into account an optional pid file |
|
345
|
|
|
|
|
|
|
# |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
my %pf_sleep_options = ( |
|
348
|
|
|
|
|
|
|
time => { optional => 1, type => SCALAR, regex => $_NumberRegexp }, |
|
349
|
|
|
|
|
|
|
); |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
sub pf_sleep ($@) { |
|
352
|
0
|
|
|
0
|
1
|
0
|
my($path, %option, $end, $sleep); |
|
353
|
|
|
|
|
|
|
|
|
354
|
0
|
|
|
|
|
0
|
$path = shift(@_); |
|
355
|
0
|
0
|
|
|
|
0
|
%option = validate(@_, \%pf_sleep_options) if @_; |
|
356
|
0
|
0
|
|
|
|
0
|
$option{time} = 1 unless defined($option{time}); |
|
357
|
0
|
0
|
|
|
|
0
|
if ($path) { |
|
358
|
0
|
0
|
|
|
|
0
|
$end = Time::HiRes::time() + $option{time} if $option{time}; |
|
359
|
0
|
|
|
|
|
0
|
while (1) { |
|
360
|
0
|
0
|
|
|
|
0
|
return(0) if pf_check($path) eq "quit"; |
|
361
|
0
|
|
|
|
|
0
|
pf_touch($path); |
|
362
|
0
|
0
|
|
|
|
0
|
last unless $option{time}; |
|
363
|
0
|
|
|
|
|
0
|
$sleep = $end - Time::HiRes::time(); |
|
364
|
0
|
0
|
|
|
|
0
|
last if $sleep <= 0; |
|
365
|
0
|
0
|
|
|
|
0
|
$sleep = 1 if $sleep > 1; |
|
366
|
0
|
|
|
|
|
0
|
Time::HiRes::sleep($sleep); |
|
367
|
|
|
|
|
|
|
} |
|
368
|
|
|
|
|
|
|
} else { |
|
369
|
0
|
0
|
|
|
|
0
|
Time::HiRes::sleep($option{time}) if $option{time}; |
|
370
|
|
|
|
|
|
|
} |
|
371
|
0
|
|
|
|
|
0
|
return(1); |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
# |
|
375
|
|
|
|
|
|
|
# export control |
|
376
|
|
|
|
|
|
|
# |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
sub import : method { |
|
379
|
1
|
|
|
1
|
|
10
|
my($pkg, %exported); |
|
380
|
|
|
|
|
|
|
|
|
381
|
1
|
|
|
|
|
3
|
$pkg = shift(@_); |
|
382
|
1
|
|
|
|
|
10
|
grep($exported{$_}++, map("pf_$_", |
|
383
|
|
|
|
|
|
|
qw(set check touch unset status quit sleep))); |
|
384
|
1
|
|
|
|
|
5
|
export_control(scalar(caller()), $pkg, \%exported, @_); |
|
385
|
|
|
|
|
|
|
} |
|
386
|
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
1; |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
__DATA__ |