line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Proc::Forking; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
########################################################### |
4
|
|
|
|
|
|
|
# Fork package |
5
|
|
|
|
|
|
|
# Gnu GPL2 license |
6
|
|
|
|
|
|
|
# |
7
|
|
|
|
|
|
|
# Forking.pm 1.49 2010 09 02 14:52 |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# |
10
|
|
|
|
|
|
|
# Fabrice Dulaunoy |
11
|
|
|
|
|
|
|
########################################################### |
12
|
|
|
|
|
|
|
# ChangeLog: |
13
|
|
|
|
|
|
|
# |
14
|
|
|
|
|
|
|
########################################################### |
15
|
4
|
|
|
4
|
|
27564
|
use strict; |
|
4
|
|
|
4
|
|
8
|
|
|
4
|
|
|
|
|
168
|
|
|
4
|
|
|
|
|
4044
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
164
|
|
16
|
|
|
|
|
|
|
|
17
|
4
|
|
|
4
|
|
3516
|
use POSIX qw(:signal_h setsid WNOHANG); |
|
4
|
|
|
4
|
|
36132
|
|
|
4
|
|
|
|
|
32
|
|
|
4
|
|
|
|
|
16
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
44
|
|
18
|
4
|
|
|
4
|
|
10760
|
use IO::File; |
|
4
|
|
|
4
|
|
52104
|
|
|
4
|
|
|
|
|
596
|
|
|
4
|
|
|
|
|
3552
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
1452
|
|
19
|
4
|
|
|
4
|
|
40
|
use Cwd; |
|
4
|
|
|
4
|
|
8
|
|
|
4
|
|
|
|
|
256
|
|
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
260
|
|
20
|
4
|
|
|
4
|
|
3508
|
use Sys::Load qw/getload/; |
|
4
|
|
|
4
|
|
3684
|
|
|
4
|
|
|
|
|
240
|
|
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
164
|
|
21
|
4
|
|
|
4
|
|
3200
|
use Sys::Prctl; |
|
4
|
|
|
4
|
|
21692
|
|
|
4
|
|
|
|
|
224
|
|
|
4
|
|
|
|
|
20
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
168
|
|
22
|
4
|
|
|
4
|
|
36
|
use Carp; |
|
4
|
|
|
4
|
|
8
|
|
|
4
|
|
|
|
|
264
|
|
|
4
|
|
|
|
|
24
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
260
|
|
23
|
|
|
|
|
|
|
|
24
|
4
|
|
|
4
|
|
20
|
use vars qw( $VERSION); |
|
4
|
|
|
4
|
|
8
|
|
|
4
|
|
|
|
|
28460
|
|
|
4
|
|
|
|
|
20
|
|
|
4
|
|
|
|
|
8
|
|
|
4
|
|
|
|
|
20400
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
$VERSION = '1.50'; |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my $DAEMON_PID; |
29
|
|
|
|
|
|
|
$SIG{ CHLD } = \&garbage_child; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
my %PID; |
32
|
|
|
|
|
|
|
my %NAME; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
my @CODE; |
35
|
|
|
|
|
|
|
$CODE[0] = [ 0, " success" ]; |
36
|
|
|
|
|
|
|
$CODE[1] = [ 1, " Can't fork a new process" ]; |
37
|
|
|
|
|
|
|
$CODE[2] = [ 2, " Can't open PID file" ]; |
38
|
|
|
|
|
|
|
$CODE[3] = [ 3, " Process already running with same PID" ]; |
39
|
|
|
|
|
|
|
$CODE[4] = [ 4, " maximun LOAD reached" ]; |
40
|
|
|
|
|
|
|
$CODE[5] = [ 5, " maximun number of processes reached" ]; |
41
|
|
|
|
|
|
|
$CODE[6] = [ 6, " error in parameters" ]; |
42
|
|
|
|
|
|
|
$CODE[7] = [ 7, " No function provided" ]; |
43
|
|
|
|
|
|
|
$CODE[8] = [ 8, " Can't fork" ]; |
44
|
|
|
|
|
|
|
$CODE[9] = [ 9, " PID already present in list of PID processes" ]; |
45
|
|
|
|
|
|
|
$CODE[10] = [ 10, " NAME already present in list of NAME processes" ]; |
46
|
|
|
|
|
|
|
$CODE[11] = [ 11, " Can't chdir" ]; |
47
|
|
|
|
|
|
|
$CODE[12] = [ 12, " Can't chroot" ]; |
48
|
|
|
|
|
|
|
$CODE[13] = [ 13, " Can't become DAEMON" ]; |
49
|
|
|
|
|
|
|
$CODE[14] = [ 14, " Can't unlink PID file" ]; |
50
|
|
|
|
|
|
|
$CODE[15] = [ 15, " maximun MEM used reached" ]; |
51
|
|
|
|
|
|
|
$CODE[16] = [ 16, " Expiration TIMEOUT reached" ]; |
52
|
|
|
|
|
|
|
$CODE[17] = [ 17, " NO expiration parameter" ]; |
53
|
|
|
|
|
|
|
$CODE[18] = [ 18, " Don't fork, NAME already present (STRICT mode enabled)" ]; |
54
|
|
|
|
|
|
|
$CODE[19] = [ 19, " Don't fork, PID_FILE already present (STRICT mode enabled)" ]; |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub daemonize |
57
|
|
|
|
|
|
|
{ |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
0
|
|
|
0
|
1
|
0
|
my @param = @_; |
61
|
0
|
|
|
|
|
0
|
my $self = shift @param; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
$SIG{ INT } = $SIG{ KILL } = $SIG{ TERM } = sub { |
64
|
0
|
|
|
0
|
|
0
|
$self->killall_childs; |
65
|
0
|
|
|
|
|
0
|
unlink $DAEMON_PID; |
66
|
0
|
|
|
|
|
0
|
exit 0 ; |
67
|
0
|
|
|
|
|
0
|
}; |
68
|
|
|
|
|
|
|
|
69
|
0
|
0
|
|
|
|
0
|
if ( @param % 2 ) |
70
|
|
|
|
|
|
|
{ |
71
|
0
|
|
|
|
|
0
|
return ( $CODE[6][0], 0, $CODE[6][1] ); |
72
|
|
|
|
|
|
|
} |
73
|
0
|
|
|
|
|
0
|
my %param = @param; |
74
|
0
|
0
|
|
|
|
0
|
my $uid = exists( $param{ uid } ) ? $param{ uid } : ''; |
75
|
0
|
0
|
|
|
|
0
|
my $gid = exists( $param{ gid } ) ? $param{ gid } : ''; |
76
|
0
|
0
|
|
|
|
0
|
my $home = exists( $param{ home } ) ? $param{ home } : ''; |
77
|
0
|
0
|
|
|
|
0
|
my $pid_file = $param{ pid_file } if exists( $param{ pid_file } ); |
78
|
0
|
0
|
|
|
|
0
|
my $name = $param{ name } if exists( $param{ name } ); |
79
|
0
|
0
|
|
|
|
0
|
if ( defined( $name ) ) |
80
|
|
|
|
|
|
|
{ |
81
|
0
|
|
|
|
|
0
|
my $exp_name = $name; |
82
|
0
|
|
|
|
|
0
|
$exp_name =~ s/##/$$/g; |
83
|
0
|
|
|
|
|
0
|
$0 = $exp_name; |
84
|
0
|
|
|
|
|
0
|
my $main_process = new Sys::Prctl(); |
85
|
0
|
|
|
|
|
0
|
$main_process->name( $0 ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
0
|
|
|
|
|
0
|
my $child = fork; |
89
|
0
|
0
|
|
|
|
0
|
if ( !defined $child ) |
90
|
|
|
|
|
|
|
{ |
91
|
0
|
|
|
|
|
0
|
return ( $CODE[13][0], 0, $CODE[13][1] ); |
92
|
|
|
|
|
|
|
} |
93
|
0
|
0
|
|
|
|
0
|
exit 0 if $child; # parent dies; |
94
|
|
|
|
|
|
|
|
95
|
0
|
0
|
|
|
|
0
|
if ( exists( $param{ pid_file } ) ) |
96
|
|
|
|
|
|
|
{ |
97
|
0
|
|
|
|
|
0
|
$pid_file =~ s/##/$$/g; |
98
|
0
|
|
|
|
|
0
|
$DAEMON_PID = $pid_file; |
99
|
0
|
|
|
|
|
0
|
my @ret = create_pid_file( $pid_file, $$ ); |
100
|
0
|
0
|
|
|
|
0
|
if ( $ret[0] ) |
101
|
|
|
|
|
|
|
{ |
102
|
|
|
|
|
|
|
# die "Another process is RUNNING\n"; |
103
|
0
|
|
|
|
|
0
|
carp "Another process is RUNNING\n"; |
104
|
0
|
|
|
|
|
0
|
return ( $CODE[3][0], 0, $CODE[3][1] ) ; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
0
|
|
|
|
|
0
|
my $luid = -1; |
109
|
0
|
|
|
|
|
0
|
my $lgid = -1; |
110
|
0
|
0
|
|
|
|
0
|
if ( $uid ne '' ) |
111
|
|
|
|
|
|
|
{ |
112
|
0
|
|
|
|
|
0
|
$luid = $uid; |
113
|
|
|
|
|
|
|
} |
114
|
0
|
0
|
|
|
|
0
|
if ( $gid ne '' ) |
115
|
|
|
|
|
|
|
{ |
116
|
0
|
|
|
|
|
0
|
$lgid = $gid; |
117
|
|
|
|
|
|
|
} |
118
|
0
|
|
|
|
|
0
|
chown $luid, $lgid, $pid_file; |
119
|
0
|
0
|
|
|
|
0
|
if ( $home ne '' ) |
120
|
|
|
|
|
|
|
{ |
121
|
0
|
|
|
|
|
0
|
local ( $>, $< ) = ( $<, $> ); |
122
|
0
|
|
|
|
|
0
|
my $cwd = $home; |
123
|
0
|
0
|
|
|
|
0
|
chdir( $cwd ) || return ( $CODE[11][0], 0, $CODE[11][1] ); |
124
|
0
|
0
|
|
|
|
0
|
chroot( $cwd ) || return ( $CODE[12][0], 0, $CODE[12][1] ); |
125
|
0
|
|
|
|
|
0
|
$< = $>; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
0
|
0
|
|
|
|
0
|
if ( $gid ne '' ) |
129
|
|
|
|
|
|
|
{ |
130
|
0
|
|
|
|
|
0
|
$) = "$gid $gid"; |
131
|
|
|
|
|
|
|
} |
132
|
|
|
|
|
|
|
|
133
|
0
|
0
|
|
|
|
0
|
if ( $uid ne '' ) |
134
|
|
|
|
|
|
|
{ |
135
|
0
|
|
|
|
|
0
|
$> = $uid; |
136
|
|
|
|
|
|
|
} |
137
|
0
|
|
|
|
|
0
|
POSIX::setsid(); |
138
|
0
|
|
|
|
|
0
|
open( STDIN, "
|
139
|
0
|
|
|
|
|
0
|
open( STDOUT, ">/dev/null" ); |
140
|
0
|
|
|
|
|
0
|
open( STDERR, ">&STDOUT" ); |
141
|
0
|
|
|
|
|
0
|
chdir '/'; |
142
|
0
|
|
|
|
|
0
|
umask( 0 ); |
143
|
0
|
|
|
|
|
0
|
$ENV{ PATH } = '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin'; |
144
|
0
|
|
|
|
|
0
|
delete @ENV{ 'IFS', 'CDPATH', 'ENV', 'BASH_ENV' }; |
145
|
0
|
|
|
|
|
0
|
$SIG{ CHLD } = \&garbage_child; |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub new |
149
|
|
|
|
|
|
|
{ |
150
|
4
|
|
|
4
|
1
|
800
|
my ( $class ) = @_; |
151
|
4
|
|
|
|
|
96
|
bless { |
152
|
|
|
|
|
|
|
_function => $_[1], |
153
|
|
|
|
|
|
|
_args => $_[2], |
154
|
|
|
|
|
|
|
_name => $_[3], |
155
|
|
|
|
|
|
|
_pid => $_[4], |
156
|
|
|
|
|
|
|
_pid_file => $_[5], |
157
|
|
|
|
|
|
|
_home => $_[6], |
158
|
|
|
|
|
|
|
_uid => $_[7], |
159
|
|
|
|
|
|
|
_gid => $_[8], |
160
|
|
|
|
|
|
|
_max_child => $_[9], |
161
|
|
|
|
|
|
|
_max_load => $_[10], |
162
|
|
|
|
|
|
|
_pids => $_[11], |
163
|
|
|
|
|
|
|
_names => $_[12], |
164
|
|
|
|
|
|
|
_max_mem => $_[13], |
165
|
|
|
|
|
|
|
_expiration => $_[14], |
166
|
|
|
|
|
|
|
_expiration_auto => $_[15], |
167
|
|
|
|
|
|
|
_start_time => $_[16], |
168
|
|
|
|
|
|
|
_eagain_sleep => $_[17], |
169
|
|
|
|
|
|
|
# _strict => $_[17], |
170
|
|
|
|
|
|
|
}, $class; |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub fork_child |
175
|
|
|
|
|
|
|
{ |
176
|
12
|
|
|
12
|
1
|
522
|
my @param = @_; |
177
|
12
|
|
|
|
|
42
|
my $self = shift @param; |
178
|
12
|
|
|
|
|
64
|
my $start_time = time; |
179
|
12
|
50
|
|
|
|
67
|
if ( @param % 2 ) |
180
|
|
|
|
|
|
|
{ |
181
|
0
|
|
|
|
|
0
|
return ( $CODE[6][0], 0, $CODE[6][1] ); |
182
|
|
|
|
|
|
|
} |
183
|
12
|
|
|
|
|
75
|
my %param = @param; |
184
|
12
|
50
|
|
|
|
58
|
if ( !exists( $param{ function } ) ) |
185
|
|
|
|
|
|
|
{ |
186
|
0
|
|
|
|
|
0
|
return ( $CODE[7][0], 0, $CODE[7][1] ); |
187
|
|
|
|
|
|
|
} |
188
|
12
|
|
|
|
|
53
|
$self->{ _function } = $param{ function }; |
189
|
12
|
50
|
|
|
|
137
|
$self->{ _args } = $param{ args } if exists( $param{ args } ); |
190
|
12
|
100
|
|
|
|
73
|
$self->{ _name } = $param{ name } if exists( $param{ name } ); |
191
|
12
|
100
|
|
|
|
130
|
$self->{ _home } = exists( $param{ home } ) ? $param{ home } : ''; |
192
|
12
|
50
|
|
|
|
82
|
$self->{ _uid } = exists( $param{ uid } ) ? $param{ uid } : ''; |
193
|
12
|
50
|
|
|
|
79
|
$self->{ _gid } = exists( $param{ gid } ) ? $param{ gid } : ''; |
194
|
12
|
50
|
|
|
|
72
|
$self->{ _eagain_sleep } = exists( $param{ eagain_sleep } ) ? $param{ eagain_sleep }: 5; ; |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
|
197
|
12
|
|
|
|
|
40
|
$self->{ _strict } = 0; |
198
|
12
|
50
|
|
|
|
51
|
if ( exists( $param{ strict } ) ) |
199
|
|
|
|
|
|
|
{ |
200
|
0
|
|
|
|
|
0
|
$self->{ _strict } = $param{ strict }; |
201
|
0
|
0
|
|
|
|
0
|
if ( exists( $self->{ _names }{ $param{ name } }{ pid } ) ) |
202
|
|
|
|
|
|
|
{ |
203
|
0
|
|
|
|
|
0
|
return ( $CODE[18][0], $self->{ _pid }, ( $param{ name } . $CODE[18][1] ) ); |
204
|
|
|
|
|
|
|
} |
205
|
0
|
0
|
|
|
|
0
|
if ( exists( $param{ pid_file } ) ) |
206
|
|
|
|
|
|
|
{ |
207
|
0
|
0
|
|
|
|
0
|
if ( -e $param{ pid_file } ) |
208
|
|
|
|
|
|
|
{ |
209
|
|
|
|
|
|
|
# pid file already exists |
210
|
0
|
|
|
|
|
0
|
my $fh = IO::File->new( $param{ pid_file } ); |
211
|
0
|
|
|
|
|
0
|
my $pid_num = <$fh>; |
212
|
0
|
|
|
|
|
0
|
close $fh; |
213
|
0
|
0
|
|
|
|
0
|
if ( kill 0 => $pid_num ) |
214
|
|
|
|
|
|
|
{ |
215
|
0
|
|
|
|
|
0
|
return ( $CODE[19][0], $pid_num, $CODE[19][1] ); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
12
|
50
|
|
|
|
90
|
$self->{ _pid_file } = exists( $param{ pid_file } ) ? $param{ pid_file } : ''; |
222
|
|
|
|
|
|
|
|
223
|
12
|
50
|
|
|
|
52
|
if ( exists( $param{ max_load } ) ) |
224
|
|
|
|
|
|
|
{ |
225
|
0
|
|
|
|
|
0
|
$self->{ _max_load } = $param{ max_load }; |
226
|
0
|
0
|
|
|
|
0
|
if ( $self->{ _max_load } <= ( getload() )[0] ) |
227
|
|
|
|
|
|
|
{ |
228
|
0
|
|
|
|
|
0
|
return ( $CODE[4][0], 0, $CODE[4][1] ); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
12
|
50
|
|
|
|
45
|
if ( exists( $param{ max_child } ) ) |
233
|
|
|
|
|
|
|
{ |
234
|
0
|
|
|
|
|
0
|
$self->{ _max_child } = $param{ max_child }; |
235
|
0
|
0
|
|
|
|
0
|
if ( $self->{ _max_child } <= ( keys %{ $self->{ _pids } } ) ) |
|
0
|
|
|
|
|
0
|
|
236
|
|
|
|
|
|
|
{ |
237
|
0
|
|
|
|
|
0
|
return ( $CODE[5][0], 0, $CODE[5][1] ); |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
12
|
50
|
|
|
|
49
|
if ( exists( $param{ max_mem } ) ) |
242
|
|
|
|
|
|
|
{ |
243
|
0
|
|
|
|
|
0
|
$self->{ _max_mem } = $param{ max_mem }; |
244
|
0
|
0
|
|
|
|
0
|
if ( $self->{ _max_mem } >= getmemfree() ) |
245
|
|
|
|
|
|
|
{ |
246
|
0
|
|
|
|
|
0
|
return ( $CODE[15][0], 0, $CODE[15][1] ); |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
12
|
50
|
|
|
|
40
|
if ( exists( $param{ expiration } ) ) |
251
|
|
|
|
|
|
|
{ |
252
|
0
|
|
|
|
|
0
|
$self->{ _expiration } = $param{ expiration } + $start_time; |
253
|
0
|
0
|
|
|
|
0
|
if ( exists( $param{ expiration_auto } ) ) |
254
|
|
|
|
|
|
|
{ |
255
|
0
|
|
|
|
|
0
|
$self->{ _expiration_auto } = $param{ expiration_auto }; |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
# else |
258
|
|
|
|
|
|
|
# { |
259
|
|
|
|
|
|
|
# $self->{ _expiration_auto } = 0; |
260
|
|
|
|
|
|
|
# } |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
else |
263
|
|
|
|
|
|
|
{ |
264
|
12
|
|
|
|
|
39
|
$self->{ _expiration } = 0; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
{ |
268
|
12
|
|
|
|
|
35
|
my $pid; |
|
12
|
|
|
|
|
18
|
|
269
|
|
|
|
|
|
|
my $ret; |
270
|
|
|
|
|
|
|
|
271
|
12
|
100
|
|
|
|
25805
|
if ( $pid = fork() ) |
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
272
|
|
|
|
|
|
|
{ |
273
|
|
|
|
|
|
|
## in parent |
274
|
9
|
|
|
|
|
184
|
$self->{ _pid } = $pid; |
275
|
9
|
|
|
|
|
117
|
my $pid_file; |
276
|
|
|
|
|
|
|
my $exp_name; |
277
|
9
|
|
|
|
|
290
|
$self->{ _start_time } = $^T; |
278
|
9
|
100
|
|
|
|
159
|
if ( defined( $self->{ _name } ) ) |
279
|
|
|
|
|
|
|
{ |
280
|
3
|
|
|
|
|
116
|
$exp_name = $self->{ _name }; |
281
|
3
|
|
|
|
|
44
|
$exp_name =~ s/##/$pid/g; |
282
|
|
|
|
|
|
|
} |
283
|
9
|
50
|
|
|
|
71
|
if ( defined( $self->{ _pid_file } ) ) |
284
|
|
|
|
|
|
|
{ |
285
|
9
|
|
|
|
|
140
|
$pid_file = $self->{ _pid_file }; |
286
|
9
|
|
|
|
|
44
|
$pid_file =~ s/##/$pid/g; |
287
|
|
|
|
|
|
|
} |
288
|
9
|
50
|
|
|
|
228
|
if ( !defined( $self->{ _pids }{ $pid } ) ) |
289
|
|
|
|
|
|
|
{ |
290
|
9
|
|
|
|
|
406
|
$self->{ _pids }{ $pid }{ name } = $exp_name; |
291
|
9
|
|
|
|
|
92
|
$self->{ _pids }{ $pid }{ start_time } = $start_time; |
292
|
9
|
50
|
|
|
|
52
|
if ( defined( $self->{ _expiration } ) ) |
293
|
|
|
|
|
|
|
{ |
294
|
9
|
|
|
|
|
75
|
$self->{ _pids }{ $pid }{ expiration } = $self->{ _expiration }; |
295
|
|
|
|
|
|
|
} |
296
|
9
|
50
|
|
|
|
48
|
if ( defined( $self->{ _expiration_auto } ) ) |
297
|
|
|
|
|
|
|
{ |
298
|
0
|
|
|
|
|
0
|
$self->{ _pids }{ $pid }{ expiration_auto } = $self->{ _expiration_auto }; |
299
|
|
|
|
|
|
|
} |
300
|
9
|
|
|
|
|
107
|
$PID{ $pid }{ name } = $exp_name; |
301
|
9
|
50
|
|
|
|
50
|
if ( defined( $self->{ _pid_file } ) ) |
302
|
|
|
|
|
|
|
{ |
303
|
9
|
|
|
|
|
106
|
$self->{ _pids }{ $pid }{ pid_file } = $pid_file; |
304
|
9
|
|
|
|
|
40
|
$PID{ $pid }{ pid_file } = $pid_file; |
305
|
|
|
|
|
|
|
} |
306
|
9
|
50
|
|
|
|
104
|
if ( defined( $self->{ _home } ) ) |
307
|
|
|
|
|
|
|
{ |
308
|
9
|
|
|
|
|
144
|
$self->{ _pids }{ $pid }{ home } = $self->{ _home }; |
309
|
9
|
|
|
|
|
30
|
$PID{ $pid }{ home } = $self->{ _home }; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
} |
312
|
|
|
|
|
|
|
else |
313
|
|
|
|
|
|
|
{ |
314
|
0
|
|
|
|
|
0
|
return ( $CODE[9][0], $self->{ _pid }, $CODE[9][1] ); |
315
|
|
|
|
|
|
|
} |
316
|
9
|
100
|
|
|
|
171
|
if ( !defined( $self->{ _names }{ $exp_name }{ pid } ) ) |
317
|
|
|
|
|
|
|
{ |
318
|
5
|
|
|
|
|
63
|
$self->{ _names }{ $exp_name }{ pid } = $pid; |
319
|
5
|
|
|
|
|
15
|
$self->{ _names }{ $exp_name }{ start_time } = $start_time; |
320
|
5
|
50
|
|
|
|
36
|
if ( defined( $self->{ _expiration } ) ) |
321
|
|
|
|
|
|
|
{ |
322
|
5
|
|
|
|
|
15
|
$self->{ _names }{ $exp_name }{ expiration } = $self->{ _expiration }; |
323
|
|
|
|
|
|
|
} |
324
|
5
|
50
|
|
|
|
36
|
if ( defined( $self->{ _expiration_auto } ) ) |
325
|
|
|
|
|
|
|
{ |
326
|
0
|
|
|
|
|
0
|
$self->{ _names }{ $exp_name }{ expiration_auto } = $self->{ _expiration_auto }; |
327
|
|
|
|
|
|
|
} |
328
|
5
|
|
|
|
|
62
|
$NAME{ $exp_name }{ pid } = $pid; |
329
|
5
|
50
|
|
|
|
33
|
if ( defined( $self->{ _pid_file } ) ) |
330
|
|
|
|
|
|
|
{ |
331
|
5
|
|
|
|
|
13
|
$self->{ _names }{ $exp_name }{ pid_file } = $pid_file; |
332
|
5
|
|
|
|
|
10
|
$NAME{ $exp_name }{ pid_file } = $pid_file; |
333
|
|
|
|
|
|
|
} |
334
|
5
|
50
|
|
|
|
16
|
if ( defined( $self->{ _home } ) ) |
335
|
|
|
|
|
|
|
{ |
336
|
5
|
|
|
|
|
34
|
$self->{ _names }{ $exp_name }{ home } = $self->{ _home }; |
337
|
5
|
|
|
|
|
13
|
$NAME{ $exp_name }{ home } = $self->{ _home }; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
} |
340
|
|
|
|
|
|
|
else |
341
|
|
|
|
|
|
|
{ |
342
|
4
|
|
|
|
|
645
|
return ( $CODE[10][0], $self->{ _pid }, ( $self->{ _name } . $CODE[10][1] ) ); |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
5
|
|
|
|
|
3890
|
return ( $CODE[0][0], $self->{ _pid }, $CODE[0][1] ); |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
elsif ( defined $pid ) |
348
|
|
|
|
|
|
|
{ |
349
|
|
|
|
|
|
|
## in child |
350
|
3
|
|
|
|
|
699
|
$SIG{ INT } = $SIG{ CHLD } = $SIG{ TERM } = 'DEFAULT'; |
351
|
3
|
100
|
|
|
|
101
|
if ( defined( $self->{ _name } ) ) |
352
|
|
|
|
|
|
|
{ |
353
|
2
|
|
|
|
|
38
|
my $exp_name = $self->{ _name }; |
354
|
2
|
|
|
|
|
69
|
$exp_name =~ s/##/$$/g; |
355
|
2
|
|
|
|
|
210
|
$0 = $exp_name; |
356
|
2
|
|
|
|
|
321
|
my $main_process = new Sys::Prctl(); |
357
|
2
|
|
|
|
|
110
|
$main_process->name( $0 ); |
358
|
|
|
|
|
|
|
} |
359
|
3
|
|
|
|
|
368
|
$self->{ _start_time } = $start_time; |
360
|
|
|
|
|
|
|
|
361
|
3
|
|
|
|
|
22
|
$self->{ _pid } = $pid; |
362
|
3
|
50
|
|
|
|
43
|
if ( $self->{ _home } ne '' ) |
363
|
|
|
|
|
|
|
{ |
364
|
0
|
|
|
|
|
0
|
local ( $>, $< ) = ( $<, $> ); |
365
|
0
|
|
|
|
|
0
|
my $cwd = $self->{ _home }; |
366
|
0
|
0
|
|
|
|
0
|
chdir( $cwd ) || return ( $CODE[11][0], 0, $CODE[11][1] ); |
367
|
0
|
0
|
|
|
|
0
|
chroot( $cwd ) || return ( $CODE[12][0], 0, $CODE[12][1] ); |
368
|
0
|
|
|
|
|
0
|
$< = $>; |
369
|
|
|
|
|
|
|
} |
370
|
|
|
|
|
|
|
|
371
|
3
|
50
|
|
|
|
35
|
if ( $self->{ _gid } ne '' ) |
372
|
|
|
|
|
|
|
{ |
373
|
0
|
|
|
|
|
0
|
my $gid = $self->{ _gid }; |
374
|
0
|
|
|
|
|
0
|
$) = "$gid $gid"; |
375
|
|
|
|
|
|
|
} |
376
|
3
|
50
|
|
|
|
19
|
if ( $self->{ _uid } ne '' ) |
377
|
|
|
|
|
|
|
{ |
378
|
0
|
|
|
|
|
0
|
$> = $self->{ _uid }; |
379
|
|
|
|
|
|
|
} |
380
|
3
|
50
|
|
|
|
93
|
if ( $self->{ _pid_file } ne '' ) |
381
|
|
|
|
|
|
|
{ |
382
|
0
|
|
|
|
|
0
|
my $pid_file = $self->{ _pid_file }; |
383
|
|
|
|
|
|
|
|
384
|
0
|
|
|
|
|
0
|
$pid_file =~ s/##/$$/g; |
385
|
|
|
|
|
|
|
|
386
|
0
|
0
|
|
|
|
0
|
if ( defined $self->{ _pid_folder } ) |
387
|
|
|
|
|
|
|
{ |
388
|
0
|
|
|
|
|
0
|
$pid_file = $self->{ _pid_folder } . $pid_file; |
389
|
|
|
|
|
|
|
} |
390
|
0
|
|
|
|
|
0
|
$ret = create_pid_file( $pid_file, $$ ); |
391
|
|
|
|
|
|
|
} |
392
|
3
|
50
|
33
|
|
|
97
|
if ( ( exists( $self->{ _expiration } ) && ( exists( $self->{ _expiration_auto } ) ) ) ) |
393
|
|
|
|
|
|
|
{ |
394
|
3
|
|
|
|
|
32
|
my $sta; |
395
|
3
|
|
|
|
|
166
|
eval { |
396
|
|
|
|
|
|
|
local $SIG{ ALRM } = sub { |
397
|
0
|
0
|
|
0
|
|
0
|
if ( defined $self->{ _pid_file } ) |
398
|
|
|
|
|
|
|
{ |
399
|
0
|
|
|
|
|
0
|
my $pid_file = $self->{ _pid_file }; |
400
|
0
|
|
|
|
|
0
|
$pid_file =~ s/##/$$/g; |
401
|
|
|
|
|
|
|
|
402
|
0
|
0
|
|
|
|
0
|
if ( -e $pid_file ) |
403
|
|
|
|
|
|
|
{ |
404
|
0
|
|
|
|
|
0
|
delete_pid_file( $pid_file ); |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
} |
407
|
0
|
|
|
|
|
0
|
return ( $CODE[16][0], 16, $CODE[16][1] ); |
408
|
|
|
|
|
|
|
# die "TIMEOUT"; |
409
|
3
|
|
|
|
|
292
|
}; |
410
|
3
|
|
|
|
|
212
|
alarm( $self->{ _expiration } - $self->{ _start_time } ); |
411
|
3
|
|
|
|
|
11
|
eval { $self->{ _function }( $self->{ _args } ); }; |
|
3
|
|
|
|
|
99
|
|
412
|
3
|
|
|
|
|
2181408
|
alarm 0; |
413
|
3
|
|
|
|
|
109
|
return ( $CODE[16][0], 16, $CODE[16][1] ); |
414
|
|
|
|
|
|
|
}; |
415
|
3
|
|
|
|
|
17
|
alarm 0; |
416
|
|
|
|
|
|
|
# if ($@ && $@ =~ /TIMEOUT/) |
417
|
3
|
50
|
|
|
|
192
|
if ( $! =~ /Interrupted system call/ ) |
418
|
|
|
|
|
|
|
{ |
419
|
0
|
|
|
|
|
0
|
return ( $CODE[16][0], 16, $CODE[16][1] ); |
420
|
|
|
|
|
|
|
} |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
else |
423
|
|
|
|
|
|
|
{ |
424
|
0
|
|
|
|
|
0
|
$self->{ _function }( $self->{ _args } ); |
425
|
|
|
|
|
|
|
} |
426
|
|
|
|
|
|
|
|
427
|
3
|
50
|
|
|
|
21
|
if ( defined $self->{ _pid_file } ) |
428
|
|
|
|
|
|
|
{ |
429
|
3
|
|
|
|
|
29
|
my $pid_file = $self->{ _pid_file }; |
430
|
3
|
|
|
|
|
18
|
$pid_file =~ s/##/$$/g; |
431
|
|
|
|
|
|
|
|
432
|
3
|
50
|
|
|
|
87
|
if ( -e $pid_file ) |
433
|
|
|
|
|
|
|
{ |
434
|
0
|
|
|
|
|
0
|
delete_pid_file( $pid_file ); |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
} |
437
|
3
|
|
|
|
|
1050
|
exit 0; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
elsif ( $! == &POSIX::EAGAIN ) |
440
|
|
|
|
|
|
|
{ |
441
|
0
|
|
|
|
|
0
|
my $o0 = $0; |
442
|
0
|
|
|
|
|
0
|
$0 = "$o0: waiting to fork"; |
443
|
|
|
|
|
|
|
# sleep 5; |
444
|
0
|
|
|
|
|
0
|
sleep $self->{ _eagain_sleep }; |
445
|
0
|
|
|
|
|
0
|
$0 = $o0; |
446
|
0
|
|
|
|
|
0
|
redo; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
else |
449
|
|
|
|
|
|
|
{ |
450
|
0
|
|
|
|
|
0
|
return ( $CODE[8][0], 0, $CODE[8][1] ); |
451
|
|
|
|
|
|
|
} |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
} |
455
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
sub kill_child |
457
|
|
|
|
|
|
|
{ |
458
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
459
|
0
|
|
|
|
|
0
|
my $pid = shift; |
460
|
0
|
|
0
|
|
|
0
|
my $signal = shift || 15; |
461
|
0
|
|
|
|
|
0
|
kill $signal => $pid; |
462
|
0
|
|
|
|
|
0
|
my ($dp , $dn) = $self->clean_childs(); |
463
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( scalar( @{$dp} ), $dp, $dn ) : scalar( @{$dp} ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
sub killall_childs |
467
|
|
|
|
|
|
|
{ |
468
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
469
|
0
|
|
0
|
|
|
0
|
my $signal = shift || 15; |
470
|
0
|
|
|
|
|
0
|
my $pids = $self->{ _pids }; |
471
|
0
|
|
|
|
|
0
|
my %pids = %{ $pids }; |
|
0
|
|
|
|
|
0
|
|
472
|
|
|
|
|
|
|
|
473
|
0
|
|
|
|
|
0
|
foreach ( keys %pids ) |
474
|
|
|
|
|
|
|
{ |
475
|
0
|
|
|
|
|
0
|
kill $signal => $_; |
476
|
|
|
|
|
|
|
} |
477
|
0
|
|
|
|
|
0
|
my ($dp , $dn) = $self->clean_childs(); |
478
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( scalar( @{$dp} ), $dp, $dn ) : scalar( @{$dp} ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
479
|
|
|
|
|
|
|
} |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
sub expirate |
482
|
|
|
|
|
|
|
{ |
483
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
484
|
0
|
|
0
|
|
|
0
|
my $signal = shift || 15; |
485
|
0
|
|
|
|
|
0
|
my $pids = $self->{ _pids }; |
486
|
0
|
|
|
|
|
0
|
my %pids = %{ $pids }; |
|
0
|
|
|
|
|
0
|
|
487
|
0
|
|
|
|
|
0
|
my $now = time; |
488
|
|
|
|
|
|
|
|
489
|
0
|
|
|
|
|
0
|
foreach my $pid ( keys %pids ) |
490
|
|
|
|
|
|
|
{ |
491
|
0
|
0
|
|
|
|
0
|
if ( $self->{ _pids }{ $pid }{ expiration } < $now ) |
492
|
|
|
|
|
|
|
{ |
493
|
0
|
|
|
|
|
0
|
kill $signal => $pid; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
} |
496
|
0
|
|
|
|
|
0
|
my ($dp , $dn) = $self->clean_childs(); |
497
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( scalar( @{$dp} ), $dp, $dn ) : scalar( @{$dp} ); |
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
498
|
|
|
|
|
|
|
} |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
sub get_expiration |
501
|
|
|
|
|
|
|
{ |
502
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
503
|
0
|
|
|
|
|
0
|
my $pid = shift; |
504
|
0
|
0
|
|
|
|
0
|
if ( exists( $self->{ _pids }{ $pid }{ expiration } ) ) |
505
|
|
|
|
|
|
|
{ |
506
|
0
|
|
|
|
|
0
|
return ( $self->{ _pids }{ $pid }{ expiration } ); |
507
|
|
|
|
|
|
|
} |
508
|
|
|
|
|
|
|
else |
509
|
|
|
|
|
|
|
{ |
510
|
0
|
|
|
|
|
0
|
return ( $CODE[17][0], 17, $CODE[17][1] ); |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
} |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
sub set_expiration |
515
|
|
|
|
|
|
|
{ |
516
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
517
|
0
|
|
|
|
|
0
|
my $pid = shift; |
518
|
0
|
|
|
|
|
0
|
my $new_expiration = shift; |
519
|
0
|
|
|
|
|
0
|
$new_expiration += time; |
520
|
|
|
|
|
|
|
|
521
|
0
|
0
|
|
|
|
0
|
if ( exists( $self->{ _pids }{ $pid }{ expiration } ) ) |
522
|
|
|
|
|
|
|
{ |
523
|
0
|
|
|
|
|
0
|
$self->{ _pids }{ $pid }{ expiration } = $new_expiration; |
524
|
0
|
|
|
|
|
0
|
my $name = $self->{ _pids }{ $pid }{ name }; |
525
|
0
|
|
|
|
|
0
|
$self->{ _names }{ $name }{ expiration } = $new_expiration; |
526
|
0
|
|
|
|
|
0
|
return ( $self->{ _pids }{ $pid }{ expiration } ); |
527
|
|
|
|
|
|
|
} |
528
|
|
|
|
|
|
|
else |
529
|
|
|
|
|
|
|
{ |
530
|
0
|
|
|
|
|
0
|
return ( $CODE[17][0], 17, $CODE[17][1] ); |
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
} |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
sub list_pids |
535
|
|
|
|
|
|
|
{ |
536
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
537
|
|
|
|
|
|
|
# $self->clean_childs(); |
538
|
0
|
|
|
|
|
0
|
return $self->{ _pids }; |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
sub list_names |
542
|
|
|
|
|
|
|
{ |
543
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
544
|
|
|
|
|
|
|
# $self->clean_childs(); |
545
|
0
|
|
|
|
|
0
|
return $self->{ _names }; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub pid_nbr |
549
|
|
|
|
|
|
|
{ |
550
|
3
|
|
|
3
|
1
|
375
|
my $self = shift; |
551
|
|
|
|
|
|
|
# $self->clean_childs(); |
552
|
3
|
|
|
|
|
9
|
return ( scalar( keys %{ $self->{ _pids } } ) ); |
|
3
|
|
|
|
|
27
|
|
553
|
|
|
|
|
|
|
} |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
sub clean_childs |
556
|
|
|
|
|
|
|
{ |
557
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
558
|
0
|
|
|
|
|
0
|
my @pid_remove_list; |
559
|
|
|
|
|
|
|
my @name_remove_list; |
560
|
0
|
|
|
|
|
0
|
foreach my $child ( keys %{ $self->{ _pids } } ) |
|
0
|
|
|
|
|
0
|
|
561
|
|
|
|
|
|
|
{ |
562
|
0
|
|
|
|
|
0
|
my $state = kill 0 => $child; |
563
|
0
|
0
|
|
|
|
0
|
if ( !$state ) |
564
|
|
|
|
|
|
|
{ |
565
|
0
|
|
|
|
|
0
|
my $name = $self->{ _pids }{ $child }{ name }; |
566
|
0
|
0
|
|
|
|
0
|
if ( defined $self->{ _pids }{ $child }{ pid_file } ) |
567
|
|
|
|
|
|
|
{ |
568
|
0
|
|
|
|
|
0
|
my $pid_file = $self->{ _pids }{ $child }{ pid_file }; |
569
|
0
|
0
|
|
|
|
0
|
if ( defined $self->{ _pids }{ $child }{ home } ) |
570
|
|
|
|
|
|
|
{ |
571
|
0
|
|
|
|
|
0
|
$pid_file = $self->{ _pids }{ $child }{ home } . $pid_file; |
572
|
|
|
|
|
|
|
} |
573
|
|
|
|
|
|
|
|
574
|
0
|
0
|
|
|
|
0
|
if ( -e $pid_file ) |
575
|
|
|
|
|
|
|
{ |
576
|
0
|
|
|
|
|
0
|
delete_pid_file( $pid_file ); |
577
|
|
|
|
|
|
|
} |
578
|
0
|
|
|
|
|
0
|
delete $self->{ _pids }{ $child }{ pid_file }; |
579
|
0
|
|
|
|
|
0
|
delete $self->{ _names }{ $name }{ pid_file }; |
580
|
|
|
|
|
|
|
} |
581
|
0
|
|
|
|
|
0
|
delete $self->{ _pids }{ $child }{ start_time }; |
582
|
0
|
|
|
|
|
0
|
delete $self->{ _pids }{ $child }{ name }; |
583
|
0
|
|
|
|
|
0
|
delete $self->{ _pids }{ $child }; |
584
|
0
|
|
|
|
|
0
|
delete $self->{ _names }{ $name }{ start_time }; |
585
|
0
|
|
|
|
|
0
|
delete $self->{ _names }{ $name }{ pid }; |
586
|
0
|
|
|
|
|
0
|
delete $self->{ _names }{ $name }; |
587
|
|
|
|
|
|
|
|
588
|
0
|
|
|
|
|
0
|
delete $NAME{ $name }{ pid }; |
589
|
0
|
|
|
|
|
0
|
delete $NAME{ $name }; |
590
|
|
|
|
|
|
|
|
591
|
0
|
|
|
|
|
0
|
push @pid_remove_list, $child; |
592
|
0
|
|
|
|
|
0
|
push @name_remove_list, $name; |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
} |
595
|
|
|
|
|
|
|
|
596
|
0
|
|
|
|
|
0
|
return \@pid_remove_list, \@name_remove_list; |
597
|
|
|
|
|
|
|
} |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
sub test_pid |
600
|
|
|
|
|
|
|
{ |
601
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
602
|
|
|
|
|
|
|
# $self->clean_childs(); |
603
|
0
|
|
|
|
|
0
|
my $child = shift; |
604
|
0
|
|
|
|
|
0
|
my $state; |
605
|
0
|
0
|
|
|
|
0
|
if ( exists $self->{ _pids }{ $child } ) |
606
|
|
|
|
|
|
|
{ |
607
|
0
|
|
|
|
|
0
|
$state = kill 0 => $child; |
608
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( $state, ( $self->{ _pids }{ $child }{ name } ) ) : $state; |
609
|
|
|
|
|
|
|
} |
610
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( 0, ( $self->{ _pids }{ $child }{ name } ) ) : $state; |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
sub test_name |
614
|
|
|
|
|
|
|
{ |
615
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
616
|
|
|
|
|
|
|
# $self->clean_childs(); |
617
|
0
|
|
|
|
|
0
|
my $name = shift; |
618
|
0
|
|
|
|
|
0
|
my $state; |
619
|
0
|
0
|
|
|
|
0
|
if ( defined( $self->{ _names }{ $name } ) ) |
620
|
|
|
|
|
|
|
{ |
621
|
0
|
|
|
|
|
0
|
$state = kill 0 => ( $self->{ _names }{ $name }{ pid } ); |
622
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( $state, ( $self->{ _names }{ $name }{ pid } ) ) : $state; |
623
|
|
|
|
|
|
|
} |
624
|
0
|
0
|
|
|
|
0
|
return wantarray ? ( 0, ( $self->{ _names }{ $name }{ pid } ) ) : $state; |
625
|
|
|
|
|
|
|
} |
626
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
sub version |
628
|
|
|
|
|
|
|
{ |
629
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
630
|
0
|
|
|
|
|
0
|
return $VERSION; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
sub create_pid_file |
634
|
|
|
|
|
|
|
{ |
635
|
0
|
|
|
0
|
0
|
0
|
my $file = shift; |
636
|
0
|
|
|
|
|
0
|
my $pid_num = shift; |
637
|
0
|
0
|
|
|
|
0
|
if ( -z $file ) |
638
|
|
|
|
|
|
|
{ |
639
|
0
|
0
|
0
|
|
|
0
|
if ( !( -w $file && unlink $file ) ) |
640
|
|
|
|
|
|
|
{ |
641
|
0
|
|
|
|
|
0
|
return ( $CODE[14][0], $pid_num, $CODE[14][1] ); |
642
|
|
|
|
|
|
|
} |
643
|
|
|
|
|
|
|
} |
644
|
0
|
0
|
|
|
|
0
|
if ( -e $file ) |
645
|
|
|
|
|
|
|
{ |
646
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
# pid file already exists |
648
|
0
|
|
|
|
|
0
|
my $fh = IO::File->new( $file ); |
649
|
0
|
|
|
|
|
0
|
my $pid_num = <$fh>; |
650
|
0
|
|
|
|
|
0
|
close $fh; |
651
|
0
|
0
|
|
|
|
0
|
if ( kill 0 => $pid_num ) |
652
|
|
|
|
|
|
|
{ |
653
|
0
|
|
|
|
|
0
|
return ( $CODE[3][0], $pid_num, $CODE[3][1] ); |
654
|
|
|
|
|
|
|
} |
655
|
0
|
0
|
0
|
|
|
0
|
if ( !( -w $file && unlink $file ) ) |
656
|
|
|
|
|
|
|
{ |
657
|
0
|
|
|
|
|
0
|
return ( $CODE[14][0], $pid_num, $CODE[14][1] ); |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
} |
660
|
0
|
|
|
|
|
0
|
my $fh = IO::File->new( $file, O_WRONLY | O_CREAT | O_EXCL, 0644 ); |
661
|
0
|
0
|
|
|
|
0
|
if ( !$fh ) { return ( $CODE[2][0], $pid_num, $CODE[2][1] ); } |
|
0
|
|
|
|
|
0
|
|
662
|
0
|
|
|
|
|
0
|
print $fh $pid_num."\n"; |
663
|
0
|
|
|
|
|
0
|
close $fh; |
664
|
0
|
|
|
|
|
0
|
return ( $CODE[0][0], $pid_num, $CODE[0][1] ); |
665
|
|
|
|
|
|
|
} |
666
|
|
|
|
|
|
|
|
667
|
|
|
|
|
|
|
sub delete_pid_file |
668
|
|
|
|
|
|
|
{ |
669
|
0
|
|
|
0
|
0
|
0
|
my $file = shift; |
670
|
0
|
0
|
|
|
|
0
|
if ( -e $file ) |
671
|
|
|
|
|
|
|
{ |
672
|
0
|
0
|
0
|
|
|
0
|
if ( !( -w $file && unlink $file ) ) |
673
|
|
|
|
|
|
|
{ |
674
|
0
|
|
|
|
|
0
|
Carp::carp "Can't unlink PID file $file"; |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
} |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
sub garbage_child |
680
|
|
|
|
|
|
|
{ |
681
|
9
|
|
|
9
|
0
|
11937022
|
while ( ( my $child = waitpid( -1, WNOHANG ) ) > 0 ) |
682
|
|
|
|
|
|
|
{ |
683
|
0
|
|
|
|
|
0
|
my $name = $PID{ $child }{ name }; |
684
|
0
|
0
|
|
|
|
0
|
if ( defined $PID{ $child }{ pid_file } ) |
685
|
|
|
|
|
|
|
{ |
686
|
0
|
|
|
|
|
0
|
my $pid_file = $PID{ $child }{ pid_file }; |
687
|
0
|
|
|
|
|
0
|
$pid_file =~ s/##/$child/g; |
688
|
|
|
|
|
|
|
|
689
|
0
|
0
|
|
|
|
0
|
if ( defined $PID{ $child }{ home } ) |
690
|
|
|
|
|
|
|
{ |
691
|
0
|
|
|
|
|
0
|
$pid_file = $PID{ $child }{ home } . $pid_file; |
692
|
|
|
|
|
|
|
} |
693
|
|
|
|
|
|
|
|
694
|
0
|
0
|
|
|
|
0
|
if ( -e $pid_file ) |
695
|
|
|
|
|
|
|
{ |
696
|
0
|
|
|
|
|
0
|
delete_pid_file( $pid_file ); |
697
|
|
|
|
|
|
|
} |
698
|
0
|
|
|
|
|
0
|
delete $PID{ $child }{ pid_file }; |
699
|
0
|
|
|
|
|
0
|
delete $NAME{ $name }{ pid_file }; |
700
|
|
|
|
|
|
|
} |
701
|
|
|
|
|
|
|
|
702
|
0
|
|
|
|
|
0
|
delete $PID{ $child }{ name }; |
703
|
0
|
|
|
|
|
0
|
delete $PID{ $child }; |
704
|
0
|
0
|
|
|
|
0
|
if ( exists $NAME{ $name } ) |
705
|
|
|
|
|
|
|
{ |
706
|
0
|
|
|
|
|
0
|
delete $NAME{ $name }{ pid }; |
707
|
0
|
|
|
|
|
0
|
delete $NAME{ $name }; |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
} |
710
|
9
|
|
|
|
|
350
|
$SIG{ CHLD } = \&garbage_child; |
711
|
|
|
|
|
|
|
} |
712
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
sub DESTROY |
714
|
|
|
|
|
|
|
{ |
715
|
0
|
|
|
0
|
|
|
my $self = shift; |
716
|
0
|
|
|
|
|
|
unlink $self->{ _pid_file }; |
717
|
|
|
|
|
|
|
} |
718
|
|
|
|
|
|
|
|
719
|
|
|
|
|
|
|
sub getmemfree |
720
|
|
|
|
|
|
|
{ |
721
|
0
|
|
|
0
|
1
|
|
undef $/; |
722
|
0
|
|
|
|
|
|
open MEM, "/proc/meminfo"; |
723
|
0
|
|
|
|
|
|
my $temp = ; |
724
|
0
|
|
|
|
|
|
close MEM; |
725
|
0
|
|
|
|
|
|
$temp =~ /MemFree:\s+(\d+) (\w+)\s/; |
726
|
0
|
|
|
|
|
|
my $mem = $1; |
727
|
0
|
|
|
|
|
|
my $unit = $2; |
728
|
0
|
0
|
|
|
|
|
if ( $unit =~ /kb/i ) |
|
|
0
|
|
|
|
|
|
729
|
|
|
|
|
|
|
{ |
730
|
0
|
|
|
|
|
|
$mem *= 1024; |
731
|
|
|
|
|
|
|
} |
732
|
|
|
|
|
|
|
elsif ( $unit =~ /mb/i ) |
733
|
|
|
|
|
|
|
{ |
734
|
0
|
|
|
|
|
|
$mem *= 1048576; |
735
|
|
|
|
|
|
|
} |
736
|
0
|
|
|
|
|
|
$temp =~ /SwapFree:\s+(\d+) (\w+)\s/; |
737
|
0
|
|
|
|
|
|
my $swap = $1; |
738
|
0
|
|
|
|
|
|
$unit = $2; |
739
|
0
|
0
|
|
|
|
|
if ( $unit =~ /kb/i ) |
|
|
0
|
|
|
|
|
|
740
|
|
|
|
|
|
|
{ |
741
|
0
|
|
|
|
|
|
$swap *= 1024; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
elsif ( $unit =~ /mb/i ) |
744
|
|
|
|
|
|
|
{ |
745
|
0
|
|
|
|
|
|
$swap *= 1048576; |
746
|
|
|
|
|
|
|
} |
747
|
0
|
|
|
|
|
|
my $tot = $mem + $swap; |
748
|
0
|
0
|
|
|
|
|
return wantarray ? ( $tot, $mem, $swap ) : $tot; |
749
|
|
|
|
|
|
|
} |
750
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
1; |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
=head1 ABSTRACT |
754
|
|
|
|
|
|
|
|
755
|
|
|
|
|
|
|
The B module provides a set of tool to fork and daemonize. |
756
|
|
|
|
|
|
|
The module fork a function code |
757
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
=head1 SYNOPSIS |
759
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
=over 3 |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
#!/usr/bin/perl |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
use strict; |
765
|
|
|
|
|
|
|
use Proc::Forking; |
766
|
|
|
|
|
|
|
use Data::Dumper; |
767
|
|
|
|
|
|
|
use Time::HiRes qw(usleep); # to allow micro sleep |
768
|
|
|
|
|
|
|
|
769
|
|
|
|
|
|
|
my $f = Proc::Forking->new(); |
770
|
|
|
|
|
|
|
$SIG{ KILL } = $SIG{ TERM } = $SIG{ INT } = sub { $f->killall_childs;sleep 1; exit }, |
771
|
|
|
|
|
|
|
$f->daemonize( |
772
|
|
|
|
|
|
|
## uid => 1000, |
773
|
|
|
|
|
|
|
## gid => 1000, |
774
|
|
|
|
|
|
|
## home => "/tmp", |
775
|
|
|
|
|
|
|
pid_file => "/tmp/master.pid" |
776
|
|
|
|
|
|
|
); |
777
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
open( STDOUT, ">>/tmp/master.log" ); |
779
|
|
|
|
|
|
|
my $nbr = 0; |
780
|
|
|
|
|
|
|
my $timemout; |
781
|
|
|
|
|
|
|
|
782
|
|
|
|
|
|
|
while ( 1 ) |
783
|
|
|
|
|
|
|
{ |
784
|
|
|
|
|
|
|
if ( $nbr < 20 ) |
785
|
|
|
|
|
|
|
{ |
786
|
|
|
|
|
|
|
my $extra = "other parameter"; |
787
|
|
|
|
|
|
|
my ( $status, $pid, $error ) = $f->fork_child( |
788
|
|
|
|
|
|
|
function => \&func, |
789
|
|
|
|
|
|
|
name => "new_name.##", |
790
|
|
|
|
|
|
|
args => [ "hello SOMEONE", 3, $extra ], |
791
|
|
|
|
|
|
|
pid_file => "/tmp/fork.##.pid", |
792
|
|
|
|
|
|
|
uid => 1000, |
793
|
|
|
|
|
|
|
gid => 1000, |
794
|
|
|
|
|
|
|
home => "/tmp", |
795
|
|
|
|
|
|
|
max_load => 5, |
796
|
|
|
|
|
|
|
max_mem => 185000000, |
797
|
|
|
|
|
|
|
expiration => 10, |
798
|
|
|
|
|
|
|
# expiration_auto => 1, |
799
|
|
|
|
|
|
|
); |
800
|
|
|
|
|
|
|
if ( $status == 4 ) # if the load become to high |
801
|
|
|
|
|
|
|
{ |
802
|
|
|
|
|
|
|
print "Max load reached, do a little nap\n"; |
803
|
|
|
|
|
|
|
usleep( 100000 ); |
804
|
|
|
|
|
|
|
next; |
805
|
|
|
|
|
|
|
} |
806
|
|
|
|
|
|
|
elsif ( $status ) # if another kind of error |
807
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
{ |
809
|
|
|
|
|
|
|
print "PID=$pid\t error=$error\n"; |
810
|
|
|
|
|
|
|
print Dumper( $f->list_names() ); |
811
|
|
|
|
|
|
|
print Dumper( $f->list_pids() ); |
812
|
|
|
|
|
|
|
} |
813
|
|
|
|
|
|
|
} |
814
|
|
|
|
|
|
|
$nbr = $f->pid_nbr; |
815
|
|
|
|
|
|
|
my ( $n, @dp, @dn ) = $f->expirate; |
816
|
|
|
|
|
|
|
if ( $n ) |
817
|
|
|
|
|
|
|
{ |
818
|
|
|
|
|
|
|
print Dumper( @dp ); |
819
|
|
|
|
|
|
|
} |
820
|
|
|
|
|
|
|
print "free=<" . scalar( $f->getmemfree ) . ">\n"; |
821
|
|
|
|
|
|
|
usleep( 100000 ); # always a good idea to put a small sleep to allow task swapper to gain some free resources |
822
|
|
|
|
|
|
|
} |
823
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
sub func |
825
|
|
|
|
|
|
|
{ |
826
|
|
|
|
|
|
|
my $ref = shift; |
827
|
|
|
|
|
|
|
my @args = @$ref; |
828
|
|
|
|
|
|
|
my ( $data, $time_out, $sockC ) = @args; |
829
|
|
|
|
|
|
|
$SIG{ USR1 } = sub { open my $log, ">>/tmp/log.s"; print $log "signal USR1 received\n"; close $log; }; |
830
|
|
|
|
|
|
|
if ( !$time_out ) |
831
|
|
|
|
|
|
|
{ |
832
|
|
|
|
|
|
|
$time_out = 3; |
833
|
|
|
|
|
|
|
} |
834
|
|
|
|
|
|
|
open my $FF, ">>/tmp/loglist"; |
835
|
|
|
|
|
|
|
print $FF $$, " start time =", $^T; |
836
|
|
|
|
|
|
|
close $FF; |
837
|
|
|
|
|
|
|
|
838
|
|
|
|
|
|
|
for ( 1 .. 4 ) |
839
|
|
|
|
|
|
|
{ |
840
|
|
|
|
|
|
|
open my $fh, ">>/tmp/log"; |
841
|
|
|
|
|
|
|
if ( defined $fh ) |
842
|
|
|
|
|
|
|
{ |
843
|
|
|
|
|
|
|
print $fh "TMOUT = $time_out " . time . " PID=$$ cwd=" . Cwd::cwd() . " name =$0\n"; |
844
|
|
|
|
|
|
|
$fh->close; |
845
|
|
|
|
|
|
|
} |
846
|
|
|
|
|
|
|
sleep $time_out + rand( 5 ); |
847
|
|
|
|
|
|
|
} |
848
|
|
|
|
|
|
|
} |
849
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
=back |
852
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
=head1 REQUIREMENT |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
The B module need the following modules |
856
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
POSIX |
858
|
|
|
|
|
|
|
IO::File |
859
|
|
|
|
|
|
|
Cwd |
860
|
|
|
|
|
|
|
Sys::Load |
861
|
|
|
|
|
|
|
|
862
|
|
|
|
|
|
|
=head1 METHODS |
863
|
|
|
|
|
|
|
|
864
|
|
|
|
|
|
|
=over 1 |
865
|
|
|
|
|
|
|
|
866
|
|
|
|
|
|
|
The Fork module is object oriented and provide the following method |
867
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
|
869
|
|
|
|
|
|
|
=back |
870
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
=head2 new |
872
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
To create of a new pool of child: |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
my $f = Proc::Forking->new(); |
876
|
|
|
|
|
|
|
|
877
|
|
|
|
|
|
|
|
878
|
|
|
|
|
|
|
=head2 fork_child |
879
|
|
|
|
|
|
|
|
880
|
|
|
|
|
|
|
To fork a process |
881
|
|
|
|
|
|
|
|
882
|
|
|
|
|
|
|
my ( $status, $pid, $error ) = $f->fork_child( |
883
|
|
|
|
|
|
|
function => \&func, |
884
|
|
|
|
|
|
|
name => "new_name.$_", |
885
|
|
|
|
|
|
|
args => [ "\thello SOMEONE",3, $other param], |
886
|
|
|
|
|
|
|
pid_file => "/tmp/fork.$_.pid", |
887
|
|
|
|
|
|
|
uid => 1000, |
888
|
|
|
|
|
|
|
gid => 1000, |
889
|
|
|
|
|
|
|
home => "/tmp",q |
890
|
|
|
|
|
|
|
max_load => 5, |
891
|
|
|
|
|
|
|
max_child => 5, |
892
|
|
|
|
|
|
|
max_mem => 1850000000, |
893
|
|
|
|
|
|
|
expiration => 20, |
894
|
|
|
|
|
|
|
expiration_auto => 1, |
895
|
|
|
|
|
|
|
strict => 1, |
896
|
|
|
|
|
|
|
eagain_sleep => 2, |
897
|
|
|
|
|
|
|
); |
898
|
|
|
|
|
|
|
|
899
|
|
|
|
|
|
|
The only mandatory parameter is the reference to the function to fork (function => \&func) |
900
|
|
|
|
|
|
|
The normal return value is an array with: 3 elements (see B) |
901
|
|
|
|
|
|
|
|
902
|
|
|
|
|
|
|
=over 2 |
903
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
=back |
905
|
|
|
|
|
|
|
|
906
|
|
|
|
|
|
|
=head3 function |
907
|
|
|
|
|
|
|
|
908
|
|
|
|
|
|
|
=over 3 |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
I is the reference to the function to use as code for the child. It is the only mandatory parameter. |
911
|
|
|
|
|
|
|
|
912
|
|
|
|
|
|
|
=back |
913
|
|
|
|
|
|
|
|
914
|
|
|
|
|
|
|
=head3 name |
915
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
=over 3 |
917
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
I is the name for the newly created process (affect new_name to $0 in the child). |
919
|
|
|
|
|
|
|
A ## (double sharp) into the name is replaced with the PID of the process created. |
920
|
|
|
|
|
|
|
|
921
|
|
|
|
|
|
|
=back |
922
|
|
|
|
|
|
|
|
923
|
|
|
|
|
|
|
=head3 home |
924
|
|
|
|
|
|
|
|
925
|
|
|
|
|
|
|
=over 3 |
926
|
|
|
|
|
|
|
|
927
|
|
|
|
|
|
|
the I provided will become the working directory of the child with a chroot. |
928
|
|
|
|
|
|
|
Be carefull for the files created into the process forked, authorizasions and paths are relative to this chroot |
929
|
|
|
|
|
|
|
|
930
|
|
|
|
|
|
|
=back |
931
|
|
|
|
|
|
|
|
932
|
|
|
|
|
|
|
=head3 uid |
933
|
|
|
|
|
|
|
|
934
|
|
|
|
|
|
|
=over 3 |
935
|
|
|
|
|
|
|
|
936
|
|
|
|
|
|
|
the child get this new I (numerical value) |
937
|
|
|
|
|
|
|
Be carefull for the files created into the process forked, authorizations and paths are relative to this chroot |
938
|
|
|
|
|
|
|
|
939
|
|
|
|
|
|
|
=back |
940
|
|
|
|
|
|
|
|
941
|
|
|
|
|
|
|
=head3 gid |
942
|
|
|
|
|
|
|
|
943
|
|
|
|
|
|
|
=over 3 |
944
|
|
|
|
|
|
|
|
945
|
|
|
|
|
|
|
the child get this new I (numerical value) |
946
|
|
|
|
|
|
|
Be carefull for the files created into the process forked, authorizations and paths are relative to this chroot |
947
|
|
|
|
|
|
|
|
948
|
|
|
|
|
|
|
=back |
949
|
|
|
|
|
|
|
|
950
|
|
|
|
|
|
|
=head3 pid_file |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
=over 3 |
953
|
|
|
|
|
|
|
|
954
|
|
|
|
|
|
|
I give the file containing the pid of the child (be care of uid, gid and chroot because the pid_file is created by the child) |
955
|
|
|
|
|
|
|
A ## (double sharp ) into the name is expanded with the PID of the process created |
956
|
|
|
|
|
|
|
|
957
|
|
|
|
|
|
|
=back |
958
|
|
|
|
|
|
|
|
959
|
|
|
|
|
|
|
=head3 max_load |
960
|
|
|
|
|
|
|
|
961
|
|
|
|
|
|
|
=over 3 |
962
|
|
|
|
|
|
|
|
963
|
|
|
|
|
|
|
if the "1 minute" load is greater than I, the process is not forked |
964
|
|
|
|
|
|
|
and the function will return [ 4, 0, "maximun LOAD reached" ] |
965
|
|
|
|
|
|
|
|
966
|
|
|
|
|
|
|
=back |
967
|
|
|
|
|
|
|
|
968
|
|
|
|
|
|
|
=head3 max_child |
969
|
|
|
|
|
|
|
|
970
|
|
|
|
|
|
|
=over 3 |
971
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
if the number of running child is greater than max_child, the process is not forked |
973
|
|
|
|
|
|
|
and the function return [ 5, 0, "maximun number of processes reached" ] |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
=back |
976
|
|
|
|
|
|
|
|
977
|
|
|
|
|
|
|
=head3 max_mem |
978
|
|
|
|
|
|
|
|
979
|
|
|
|
|
|
|
=over 3 |
980
|
|
|
|
|
|
|
|
981
|
|
|
|
|
|
|
if the total free memory is lower than this value, the process is not forked |
982
|
|
|
|
|
|
|
and the function will return [ 15, 0, "maximun MEM used reached" ] |
983
|
|
|
|
|
|
|
|
984
|
|
|
|
|
|
|
=back |
985
|
|
|
|
|
|
|
|
986
|
|
|
|
|
|
|
=head3 expiration |
987
|
|
|
|
|
|
|
|
988
|
|
|
|
|
|
|
=over 3 |
989
|
|
|
|
|
|
|
|
990
|
|
|
|
|
|
|
it is a value linked with each forked process to allow the function expirate() |
991
|
|
|
|
|
|
|
to kill the process if it is still running after that expiration time |
992
|
|
|
|
|
|
|
The expiration value write in list_pids and list_names are this value (in sec ) + the start_time |
993
|
|
|
|
|
|
|
(to allow set_expiration to modify the value) |
994
|
|
|
|
|
|
|
|
995
|
|
|
|
|
|
|
=back |
996
|
|
|
|
|
|
|
|
997
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
=head3 expiration_auto |
999
|
|
|
|
|
|
|
|
1000
|
|
|
|
|
|
|
=over 3 |
1001
|
|
|
|
|
|
|
|
1002
|
|
|
|
|
|
|
if defined, the child kill themselve after the defined expiration time (!!! the set_expiration function is not able to modify this expiration time) |
1003
|
|
|
|
|
|
|
|
1004
|
|
|
|
|
|
|
=back |
1005
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
|
1007
|
|
|
|
|
|
|
=head3 strict |
1008
|
|
|
|
|
|
|
|
1009
|
|
|
|
|
|
|
=over 3 |
1010
|
|
|
|
|
|
|
|
1011
|
|
|
|
|
|
|
if defined, the process is not forked if the NAME is already in process table, or if the PID_FILE id present and a corresponding process is still running |
1012
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
BECARE, because the test is done before the fork, the NAME and the PID_FILE is not expanded with the child PID |
1014
|
|
|
|
|
|
|
|
1015
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
=back |
1017
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
|
1019
|
|
|
|
|
|
|
=head3 eagain_sleep |
1020
|
|
|
|
|
|
|
|
1021
|
|
|
|
|
|
|
=over 3 |
1022
|
|
|
|
|
|
|
|
1023
|
|
|
|
|
|
|
timeout between a new try of forking if POSIX::EAGAIN error occor ( default 5 second); |
1024
|
|
|
|
|
|
|
|
1025
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
=back |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
=head2 kill_child |
1029
|
|
|
|
|
|
|
|
1030
|
|
|
|
|
|
|
$f->kill_child(PID[,SIGNAL]); |
1031
|
|
|
|
|
|
|
|
1032
|
|
|
|
|
|
|
This function kill with a signal 15 (by default) the process with the provided PID. |
1033
|
|
|
|
|
|
|
An optional signal could be provided. |
1034
|
|
|
|
|
|
|
This function return the number of childs killed, a ref to a list of PID killed, a ref to a list of names killed. |
1035
|
|
|
|
|
|
|
|
1036
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
=head2 killall_childs |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
$f->killall_childs([SIGNAL]); |
1040
|
|
|
|
|
|
|
|
1041
|
|
|
|
|
|
|
This function kills all processes with a signal 15 (by default). |
1042
|
|
|
|
|
|
|
An optional signal could be provided. |
1043
|
|
|
|
|
|
|
This function return the number of childs killed, a ref to a list of PID killed, a ref to a list of names killed. |
1044
|
|
|
|
|
|
|
|
1045
|
|
|
|
|
|
|
=head2 list_pids |
1046
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
my $pid = $f->list_pids; |
1048
|
|
|
|
|
|
|
|
1049
|
|
|
|
|
|
|
This function return a reference to a HASH like |
1050
|
|
|
|
|
|
|
|
1051
|
|
|
|
|
|
|
{ |
1052
|
|
|
|
|
|
|
'1458' => { |
1053
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.3.pid', |
1054
|
|
|
|
|
|
|
'name' => 'new_name.3', |
1055
|
|
|
|
|
|
|
'home' => '/tmp', |
1056
|
|
|
|
|
|
|
'expiration' => '1105369235', |
1057
|
|
|
|
|
|
|
'start_time' => 1104998945 |
1058
|
|
|
|
|
|
|
}, |
1059
|
|
|
|
|
|
|
'1454' => { |
1060
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.1.pid', |
1061
|
|
|
|
|
|
|
'name' => 'new_name.1', |
1062
|
|
|
|
|
|
|
'home' => '/tmp' |
1063
|
|
|
|
|
|
|
}, |
1064
|
|
|
|
|
|
|
'1456' => { |
1065
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.2.pid', |
1066
|
|
|
|
|
|
|
'name' => 'new_name.2', |
1067
|
|
|
|
|
|
|
'home' => '/tmp' |
1068
|
|
|
|
|
|
|
} |
1069
|
|
|
|
|
|
|
}; |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
|
1072
|
|
|
|
|
|
|
The I element in the HASH is only present if we provide the corresponding tag in the constructor B |
1073
|
|
|
|
|
|
|
Same for I element |
1074
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
=head2 list_names |
1076
|
|
|
|
|
|
|
|
1077
|
|
|
|
|
|
|
my $name = $f->list_names; |
1078
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
This function return a reference to a HASH like |
1080
|
|
|
|
|
|
|
|
1081
|
|
|
|
|
|
|
{ |
1082
|
|
|
|
|
|
|
'new_name.2' => { |
1083
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.2.pid', |
1084
|
|
|
|
|
|
|
'pid' => 1456, |
1085
|
|
|
|
|
|
|
'home' => '/tmp' |
1086
|
|
|
|
|
|
|
'expiration' => '1104999045', |
1087
|
|
|
|
|
|
|
'start_time' => 1104998945 |
1088
|
|
|
|
|
|
|
}, |
1089
|
|
|
|
|
|
|
'new_name.3' => { |
1090
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.3.pid', |
1091
|
|
|
|
|
|
|
'pid' => 1458, |
1092
|
|
|
|
|
|
|
'home' => '/tmp' |
1093
|
|
|
|
|
|
|
}, |
1094
|
|
|
|
|
|
|
'new_name.1' => { |
1095
|
|
|
|
|
|
|
'pid_file' => '/tmp/fork.1.pid', |
1096
|
|
|
|
|
|
|
'pid' => 1454, |
1097
|
|
|
|
|
|
|
'home' => '/tmp' |
1098
|
|
|
|
|
|
|
} |
1099
|
|
|
|
|
|
|
}; |
1100
|
|
|
|
|
|
|
|
1101
|
|
|
|
|
|
|
The I element in the HASH is only present if we provide the corresponding tag in the constructor B |
1102
|
|
|
|
|
|
|
Same for I element |
1103
|
|
|
|
|
|
|
|
1104
|
|
|
|
|
|
|
=head2 expirate |
1105
|
|
|
|
|
|
|
|
1106
|
|
|
|
|
|
|
my ($n, $dp, n ) =$f->expirate([signal]) |
1107
|
|
|
|
|
|
|
|
1108
|
|
|
|
|
|
|
This function test if child reach the expiration time and kill if necessary with the optional signal (default 15). |
1109
|
|
|
|
|
|
|
In scalar context, this function return the number of childs killed. |
1110
|
|
|
|
|
|
|
In array context, this function return the number of childs killed, a ref to a list of PID killed, a ref to a list of names killed. |
1111
|
|
|
|
|
|
|
|
1112
|
|
|
|
|
|
|
=head2 get_expirate |
1113
|
|
|
|
|
|
|
|
1114
|
|
|
|
|
|
|
$f->get_expirate(PID) |
1115
|
|
|
|
|
|
|
|
1116
|
|
|
|
|
|
|
This function return the expiration time for the PID process provided |
1117
|
|
|
|
|
|
|
Be care!!! If called from a child, you could only receive the value of child forked before the child from where you call that function |
1118
|
|
|
|
|
|
|
|
1119
|
|
|
|
|
|
|
=head2 set_expirate |
1120
|
|
|
|
|
|
|
|
1121
|
|
|
|
|
|
|
$f->set_expirate(PID, EXP) |
1122
|
|
|
|
|
|
|
|
1123
|
|
|
|
|
|
|
This function set the expiration time for the PID process provided. |
1124
|
|
|
|
|
|
|
The new expiration time is the value + the present time. |
1125
|
|
|
|
|
|
|
This function is only useable fron main program (not childs) |
1126
|
|
|
|
|
|
|
|
1127
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
=head2 getmemfree |
1129
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
$f->getmemfree |
1131
|
|
|
|
|
|
|
|
1132
|
|
|
|
|
|
|
In scalar context, this function return the total free memory (real + swap). |
1133
|
|
|
|
|
|
|
In array context, this function return ( total_memory, real_memory, swap_memory). |
1134
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
|
1136
|
|
|
|
|
|
|
=head2 pid_nbr |
1137
|
|
|
|
|
|
|
|
1138
|
|
|
|
|
|
|
$f->pid_nbr |
1139
|
|
|
|
|
|
|
|
1140
|
|
|
|
|
|
|
This function return the number of process |
1141
|
|
|
|
|
|
|
|
1142
|
|
|
|
|
|
|
=head2 clean_childs |
1143
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
my (@pid_removed , @name_removed) =$f->clean_childs |
1145
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
This function return a ref to a list list of pid(s) and a ref to a list of name(s) removed because no more responding |
1147
|
|
|
|
|
|
|
|
1148
|
|
|
|
|
|
|
=head2 test_pid |
1149
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
my @state = $f->test_pid(PID); |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
In ARRAY context, this function return a ARRAY with |
1153
|
|
|
|
|
|
|
the first element is the status (1 = running and 0 = not running) |
1154
|
|
|
|
|
|
|
the second element is the NAME of process if the process with the PID is present in pid list and running |
1155
|
|
|
|
|
|
|
In SCALAR contect, this function return the status (1 = running and 0 = not running) |
1156
|
|
|
|
|
|
|
|
1157
|
|
|
|
|
|
|
=head2 test_name |
1158
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
my @state = $f->test_pid(NAME); |
1160
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
In ARRAY context, this function return a ARRAY with |
1162
|
|
|
|
|
|
|
the first element is the status (1 = running and 0 = not running) |
1163
|
|
|
|
|
|
|
the second element is the PID of the process if the process with the NAME is present in name list and running. |
1164
|
|
|
|
|
|
|
In SCALAR contect, this function return the status (1 = running and 0 = not running) |
1165
|
|
|
|
|
|
|
|
1166
|
|
|
|
|
|
|
=head2 version |
1167
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
$f->version; |
1169
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
Return the version number |
1171
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
=head2 daemonize |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
$f->daemonize( |
1175
|
|
|
|
|
|
|
uid=>1000, |
1176
|
|
|
|
|
|
|
gid => 1000, |
1177
|
|
|
|
|
|
|
home => "/tmp", |
1178
|
|
|
|
|
|
|
pid_file => "/tmp/master.pid" |
1179
|
|
|
|
|
|
|
name => "DAEMON" |
1180
|
|
|
|
|
|
|
); |
1181
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
This function put the main process in daemon mode and detaches it from console |
1183
|
|
|
|
|
|
|
All parameter are optional |
1184
|
|
|
|
|
|
|
The I is always created in absolute path, before any chroot either if I is provided. |
1185
|
|
|
|
|
|
|
After it's creation, the file is chmod according to the provided uid and gig |
1186
|
|
|
|
|
|
|
When process is kill, the pid_file is deleted |
1187
|
|
|
|
|
|
|
|
1188
|
|
|
|
|
|
|
=head3 uid |
1189
|
|
|
|
|
|
|
|
1190
|
|
|
|
|
|
|
=over 3 |
1191
|
|
|
|
|
|
|
|
1192
|
|
|
|
|
|
|
the process get this new uid (numerical value) |
1193
|
|
|
|
|
|
|
|
1194
|
|
|
|
|
|
|
=back |
1195
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
=head3 gid |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
=over 3 |
1199
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
the process get this new gid (numerical value) |
1201
|
|
|
|
|
|
|
|
1202
|
|
|
|
|
|
|
=back |
1203
|
|
|
|
|
|
|
|
1204
|
|
|
|
|
|
|
=head3 home |
1205
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
=over 3 |
1207
|
|
|
|
|
|
|
|
1208
|
|
|
|
|
|
|
the path provided become the working directory of the child with a chroot |
1209
|
|
|
|
|
|
|
|
1210
|
|
|
|
|
|
|
=back |
1211
|
|
|
|
|
|
|
|
1212
|
|
|
|
|
|
|
=head3 pid_file |
1213
|
|
|
|
|
|
|
|
1214
|
|
|
|
|
|
|
I specified the path to the pid_file for the child |
1215
|
|
|
|
|
|
|
Be carefull of uid, gid and chroot because the pid_file is created by the child) |
1216
|
|
|
|
|
|
|
|
1217
|
|
|
|
|
|
|
=head3 name |
1218
|
|
|
|
|
|
|
|
1219
|
|
|
|
|
|
|
=over 3 |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
I is the name for the newly created process (affect new_name to $0 in the child). |
1222
|
|
|
|
|
|
|
A ## (double sharp ) into the name is replaced with the PID of the process created. |
1223
|
|
|
|
|
|
|
|
1224
|
|
|
|
|
|
|
=back |
1225
|
|
|
|
|
|
|
|
1226
|
|
|
|
|
|
|
=head1 RETURN VALUE |
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
I constructor returns an array of 3 elements: |
1229
|
|
|
|
|
|
|
|
1230
|
|
|
|
|
|
|
1) the numerical value of the status |
1231
|
|
|
|
|
|
|
2) th epid if the fork succeed |
1232
|
|
|
|
|
|
|
3) the text of the status |
1233
|
|
|
|
|
|
|
|
1234
|
|
|
|
|
|
|
the different possible values are: |
1235
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
[ 0, PID, "success" ]; |
1237
|
|
|
|
|
|
|
[ 1, 0, "Can't fork a new process" ]; |
1238
|
|
|
|
|
|
|
[ 2, PID, "Can't open PID file" ]; |
1239
|
|
|
|
|
|
|
[ 3, PID, "Process already running with same PID" ]; |
1240
|
|
|
|
|
|
|
[ 4, 0, "maximun LOAD reached" ]; |
1241
|
|
|
|
|
|
|
[ 5, 0, "maximun number of processes reached" ]; |
1242
|
|
|
|
|
|
|
[ 6, 0, "error in parameters" ]; |
1243
|
|
|
|
|
|
|
[ 7, 0, "No function provided" ]; |
1244
|
|
|
|
|
|
|
[ 8, 0 "Can't fork" ]; |
1245
|
|
|
|
|
|
|
[ 9, PID, "PID already present in list of PID processes" ]; |
1246
|
|
|
|
|
|
|
[ 10, PID, "NAME already present in list of NAME processes" ]; |
1247
|
|
|
|
|
|
|
[ 11, 0, "Can't chdir" ]; |
1248
|
|
|
|
|
|
|
[ 12, 0 "Can't chroot" ]; |
1249
|
|
|
|
|
|
|
[ 13, 0, "Can't become DAEMON" ]; |
1250
|
|
|
|
|
|
|
[ 14, PID, "Can't unlink PID file" ]; |
1251
|
|
|
|
|
|
|
[ 15, 0, "maximun MEM used reached" ]; |
1252
|
|
|
|
|
|
|
[ 16, 16, "Expiration TIMEOUT reached" ]; |
1253
|
|
|
|
|
|
|
[ 17, 16, "NO expiration parameter" ]; |
1254
|
|
|
|
|
|
|
[ 18, " Don't fork, NAME already present (STRICT mode enbled)" ]; |
1255
|
|
|
|
|
|
|
[ 19, " Don't fork, PID_FILE already present (STRICT mode enbled)" ]; |
1256
|
|
|
|
|
|
|
|
1257
|
|
|
|
|
|
|
=head1 EXAMPLES |
1258
|
|
|
|
|
|
|
|
1259
|
|
|
|
|
|
|
#!/usr/bin/perl |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
use strict; |
1262
|
|
|
|
|
|
|
use Proc::Forking; |
1263
|
|
|
|
|
|
|
use Data::Dumper; |
1264
|
|
|
|
|
|
|
use Cache::FastMmap; |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
my $Cache = Cache::FastMmap->new( raw_values => 1 ); |
1267
|
|
|
|
|
|
|
my $f = Proc::Forking->new(); |
1268
|
|
|
|
|
|
|
|
1269
|
|
|
|
|
|
|
my $nbr = 0; |
1270
|
|
|
|
|
|
|
my $timemout; |
1271
|
|
|
|
|
|
|
my $flag = 1; |
1272
|
|
|
|
|
|
|
$SIG{ INT } = $SIG{ TERM } = sub { $flag = 0; }; |
1273
|
|
|
|
|
|
|
|
1274
|
|
|
|
|
|
|
while ( $flag ) |
1275
|
|
|
|
|
|
|
{ |
1276
|
|
|
|
|
|
|
if ( $nbr < 5 ) |
1277
|
|
|
|
|
|
|
{ |
1278
|
|
|
|
|
|
|
my $extra = "other parameter"; |
1279
|
|
|
|
|
|
|
my ( $status, $pid, $error ) = $f->fork_child( |
1280
|
|
|
|
|
|
|
function => \&func, |
1281
|
|
|
|
|
|
|
name => "new_name.##", |
1282
|
|
|
|
|
|
|
args => [ "hello SOMEONE", ( 300 + rand( 100 ) ), $extra ], |
1283
|
|
|
|
|
|
|
pid_file => "/tmp/fork.##.pid", |
1284
|
|
|
|
|
|
|
# uid => 1000, |
1285
|
|
|
|
|
|
|
# gid => 1000, |
1286
|
|
|
|
|
|
|
# home => "/tmp", |
1287
|
|
|
|
|
|
|
# max_load => 5, |
1288
|
|
|
|
|
|
|
# max_mem => 1850000000, |
1289
|
|
|
|
|
|
|
# expiration_auto => 0, |
1290
|
|
|
|
|
|
|
expiration => 10 + rand( 10 ), |
1291
|
|
|
|
|
|
|
); |
1292
|
|
|
|
|
|
|
if ( $status == 4 ) # if the load become to high |
1293
|
|
|
|
|
|
|
{ |
1294
|
|
|
|
|
|
|
print "Max load reached, do a little nap\n"; |
1295
|
|
|
|
|
|
|
usleep( 100000 ); |
1296
|
|
|
|
|
|
|
next; |
1297
|
|
|
|
|
|
|
} |
1298
|
|
|
|
|
|
|
elsif ( $status ) # if another kind of error |
1299
|
|
|
|
|
|
|
{ |
1300
|
|
|
|
|
|
|
print "PID=$pid\t error=$error\n"; |
1301
|
|
|
|
|
|
|
} |
1302
|
|
|
|
|
|
|
} |
1303
|
|
|
|
|
|
|
$nbr = $f->pid_nbr; |
1304
|
|
|
|
|
|
|
print "nbr=$nbr\n"; |
1305
|
|
|
|
|
|
|
|
1306
|
|
|
|
|
|
|
foreach ( keys %list ) |
1307
|
|
|
|
|
|
|
{ |
1308
|
|
|
|
|
|
|
my $val = $Cache->get( $_ ); |
1309
|
|
|
|
|
|
|
if ( $val ) |
1310
|
|
|
|
|
|
|
{ |
1311
|
|
|
|
|
|
|
$Cache->remove( $_ ); |
1312
|
|
|
|
|
|
|
$f->set_expiration( $_, $val ); |
1313
|
|
|
|
|
|
|
print "*********PID=$_ val=$val\n"; |
1314
|
|
|
|
|
|
|
} |
1315
|
|
|
|
|
|
|
} |
1316
|
|
|
|
|
|
|
sleep 1; |
1317
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
my ($n,@dp,@dn)=$f->expirate; |
1319
|
|
|
|
|
|
|
if($n) |
1320
|
|
|
|
|
|
|
{ |
1321
|
|
|
|
|
|
|
print Dumper(@dp); |
1322
|
|
|
|
|
|
|
} |
1323
|
|
|
|
|
|
|
} |
1324
|
|
|
|
|
|
|
|
1325
|
|
|
|
|
|
|
|
1326
|
|
|
|
|
|
|
|
1327
|
|
|
|
|
|
|
sub func |
1328
|
|
|
|
|
|
|
{ |
1329
|
|
|
|
|
|
|
my $ref = shift; |
1330
|
|
|
|
|
|
|
my @args = @$ref; |
1331
|
|
|
|
|
|
|
my ( $data, $time_out, $sockC ) = @args; |
1332
|
|
|
|
|
|
|
$SIG{ USR1 } = sub { open my $log, ">>/tmp/log.s"; print $log "signal USR1 received\n"; close $log; }; |
1333
|
|
|
|
|
|
|
$SIG{ USR2 } = sub { open my $log, ">>/tmp/log.s"; print $log "signal USR2 received for process $$ \n"; close $log; $Cache->set( $$, 123 ); }; |
1334
|
|
|
|
|
|
|
if ( !$time_out ) |
1335
|
|
|
|
|
|
|
{ |
1336
|
|
|
|
|
|
|
$time_out = 3; |
1337
|
|
|
|
|
|
|
} |
1338
|
|
|
|
|
|
|
|
1339
|
|
|
|
|
|
|
open my $FF, ">>/tmp/loglist"; |
1340
|
|
|
|
|
|
|
print $FF "$$ free=<" . scalar( $f->getmemfree ) . ">\n"; |
1341
|
|
|
|
|
|
|
close $FF; |
1342
|
|
|
|
|
|
|
|
1343
|
|
|
|
|
|
|
while ( 1 ) |
1344
|
|
|
|
|
|
|
{ |
1345
|
|
|
|
|
|
|
open my $fh, ">>/tmp/log"; |
1346
|
|
|
|
|
|
|
if ( defined $fh ) |
1347
|
|
|
|
|
|
|
{ |
1348
|
|
|
|
|
|
|
print $fh "$$ expiration=<" . $f->get_expiration . ">\n"; |
1349
|
|
|
|
|
|
|
print $fh "TMOUT = $time_out " . time . " PID=$$ cwd=" . Cwd::cwd() . " name =$0\n"; |
1350
|
|
|
|
|
|
|
$fh->close; |
1351
|
|
|
|
|
|
|
} |
1352
|
|
|
|
|
|
|
sleep $time_out + rand( 5 ); |
1353
|
|
|
|
|
|
|
} |
1354
|
|
|
|
|
|
|
} |
1355
|
|
|
|
|
|
|
|
1356
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
|
1358
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
=head1 TODO |
1360
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
=over |
1362
|
|
|
|
|
|
|
|
1363
|
|
|
|
|
|
|
=item * |
1364
|
|
|
|
|
|
|
|
1365
|
|
|
|
|
|
|
May be a kind of IPC |
1366
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
=item * |
1368
|
|
|
|
|
|
|
|
1369
|
|
|
|
|
|
|
A log, debug and/or syslog part |
1370
|
|
|
|
|
|
|
|
1371
|
|
|
|
|
|
|
=item * |
1372
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
A good test.pl for the install |
1374
|
|
|
|
|
|
|
|
1375
|
|
|
|
|
|
|
=back |
1376
|
|
|
|
|
|
|
|
1377
|
|
|
|
|
|
|
=head1 AUTHOR |
1378
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
Fabrice Dulaunoy |
1380
|
|
|
|
|
|
|
|
1381
|
|
|
|
|
|
|
15 July 2009 |
1382
|
|
|
|
|
|
|
|
1383
|
|
|
|
|
|
|
=head1 LICENSE |
1384
|
|
|
|
|
|
|
|
1385
|
|
|
|
|
|
|
Under the GNU GPL2 |
1386
|
|
|
|
|
|
|
|
1387
|
|
|
|
|
|
|
|
1388
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public |
1389
|
|
|
|
|
|
|
License as published by the Free Software Foundation; either version 2 of the License, |
1390
|
|
|
|
|
|
|
or (at your option) any later version. |
1391
|
|
|
|
|
|
|
|
1392
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; |
1393
|
|
|
|
|
|
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
1394
|
|
|
|
|
|
|
See the GNU General Public License for more details. |
1395
|
|
|
|
|
|
|
|
1396
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along with this program; |
1397
|
|
|
|
|
|
|
if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
1398
|
|
|
|
|
|
|
|
1399
|
|
|
|
|
|
|
Proc::Forking Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 DULAUNOY Fabrice Proc::Forking comes with ABSOLUTELY NO WARRANTY; |
1400
|
|
|
|
|
|
|
for details See: L |
1401
|
|
|
|
|
|
|
This is free software, and you are welcome to redistribute it under certain conditions; |
1402
|
|
|
|
|
|
|
|