Skip to content

Commit 3b0bee1

Browse files
bdracotoddr
authored andcommitted
Try non-blocking flock before expensive alarm setup
case CPANEL-21250 queueprocd setups up signal handlers and 2x alarms every loop. This is very expensive since most calls can just be a non-blocking flock. We can avoid this overhead most of the time
1 parent 685f596 commit 3b0bee1

2 files changed

Lines changed: 53 additions & 22 deletions

File tree

lib/cPanel/StateFile.pm

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,23 @@ sub import {
194194

195195
if ( $state_file->{file_handle} ) {
196196

197-
# TODO probably need to check for failure, but then what do I do?
198-
eval {
199-
local $SIG{'ALRM'} = sub { die "flock 8 timeout\n"; };
200-
my $orig_alarm = alarm $state_file->{flock_timeout};
201-
flock $state_file->{file_handle}, 8;
202-
alarm $orig_alarm;
203-
};
197+
# Try a non-blocking call first as
198+
# it will avoid two alarm syscalls
199+
# if possible.
200+
# If the nonblocking call does not
201+
# complete right away we fallback to
202+
# the full expensive
203+
# signal handler setup/alarm/flock/alarm call
204+
if ( !flock $state_file->{file_handle}, 8 | Fcntl::LOCK_NB() ) {
205+
206+
# TODO probably need to check for failure, but then what do I do?
207+
eval {
208+
local $SIG{'ALRM'} = sub { die "flock 8 timeout\n"; };
209+
my $orig_alarm = alarm $state_file->{flock_timeout};
210+
flock $state_file->{file_handle}, 8;
211+
alarm $orig_alarm;
212+
};
213+
}
204214
close $state_file->{file_handle};
205215
$state_file->{file_handle} = undef;
206216

@@ -241,21 +251,32 @@ sub import {
241251

242252
open my $fh, $mode, $state_file->{file_name}
243253
or $state_file->throw("Unable to open state file '$state_file->{file_name}': $!");
244-
eval {
245-
local $SIG{'ALRM'} = sub { die "flock 2 timeout\n"; };
246-
my $orig_alarm = alarm $state_file->{flock_timeout};
247-
flock $fh, 2;
248-
alarm $orig_alarm;
249-
1;
250-
} or do {
251-
close($fh);
252-
if ( $@ eq "flock 2 timeout\n" ) {
253-
$state_file->throw('Guard timed out trying to open state file.');
254-
}
255-
else {
256-
$state_file->throw($@);
257-
}
258-
};
254+
255+
# Try a non-blocking call first as
256+
# it will avoid two alarm syscalls
257+
# if possible.
258+
# If the nonblocking call does not
259+
# complete right away we fallback to
260+
# the full expensive
261+
# signal handler setup/alarm/flock/alarm call
262+
if ( !flock $fh, 2 | Fcntl::LOCK_NB() ) {
263+
264+
eval {
265+
local $SIG{'ALRM'} = sub { die "flock 2 timeout\n"; };
266+
my $orig_alarm = alarm $state_file->{flock_timeout};
267+
flock $fh, 2;
268+
alarm $orig_alarm;
269+
1;
270+
} or do {
271+
close($fh);
272+
if ( $@ eq "flock 2 timeout\n" ) {
273+
$state_file->throw('Guard timed out trying to open state file.');
274+
}
275+
else {
276+
$state_file->throw($@);
277+
}
278+
};
279+
}
259280
$state_file->{file_handle} = $fh;
260281
}
261282

lib/cPanel/StateFile/FileLocker.pm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,16 @@ sub _info {
145145
# returns undef on success or "Timeout on flock\n" if it timed out.
146146
sub _flock_timeout {
147147
my ( $fh, $how, $when ) = @_;
148+
149+
# Try a non-blocking call first as
150+
# it will avoid two alarm syscalls
151+
# if possible.
152+
# If the nonblocking call does not
153+
# complete right away we fallback to
154+
# the full expensive
155+
# signal handler setup/alarm/flock/alarm call
156+
return undef if flock $fh, $how | Fcntl::LOCK_NB();
157+
148158
my $orig_alarm;
149159
eval {
150160
local $SIG{'ALRM'} = sub { die "Timeout on flock\n"; };

0 commit comments

Comments
 (0)