Filename | /usr/local/lib/perl5/site_perl/Mail/SpamAssassin/Locker/UnixNFSSafe.pm |
Statements | Executed 149 statements in 6.75ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 992µs | 3.86ms | BEGIN@26 | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 2 | 2 | 692µs | 2.63ms | safe_lock | Mail::SpamAssassin::Locker::UnixNFSSafe::
5 | 3 | 1 | 629µs | 629µs | CORE:unlink (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 1 | 1 | 610µs | 610µs | CORE:sysopen (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 2 | 2 | 606µs | 5.64s | safe_unlock | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 1 | 1 | 416µs | 416µs | CORE:open (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
4 | 2 | 1 | 247µs | 247µs | CORE:print (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 1 | 1 | 139µs | 139µs | CORE:link (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
4 | 2 | 1 | 137µs | 137µs | CORE:lstat (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 58µs | 74µs | BEGIN@20 | Mail::SpamAssassin::Locker::UnixNFSSafe::
4 | 2 | 1 | 44µs | 44µs | CORE:close (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 35µs | 107µs | BEGIN@23 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 33µs | 267µs | BEGIN@28 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 31µs | 65µs | new | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 30µs | 135µs | BEGIN@27 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 30µs | 186µs | BEGIN@30 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 26µs | 220µs | BEGIN@57 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 25µs | 32µs | BEGIN@22 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 23µs | 63µs | BEGIN@21 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 21µs | 100µs | BEGIN@33 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 20µs | 3.10ms | BEGIN@31 | Mail::SpamAssassin::Locker::UnixNFSSafe::
2 | 1 | 1 | 18µs | 18µs | CORE:stat (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 17µs | 17µs | BEGIN@29 | Mail::SpamAssassin::Locker::UnixNFSSafe::
1 | 1 | 1 | 16µs | 16µs | BEGIN@25 | Mail::SpamAssassin::Locker::UnixNFSSafe::
4 | 2 | 1 | 10µs | 10µs | CORE:umask (opcode) | Mail::SpamAssassin::Locker::UnixNFSSafe::
0 | 0 | 0 | 0s | 0s | refresh_lock | Mail::SpamAssassin::Locker::UnixNFSSafe::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # <@LICENSE> | ||||
2 | # Licensed to the Apache Software Foundation (ASF) under one or more | ||||
3 | # contributor license agreements. See the NOTICE file distributed with | ||||
4 | # this work for additional information regarding copyright ownership. | ||||
5 | # The ASF licenses this file to you under the Apache License, Version 2.0 | ||||
6 | # (the "License"); you may not use this file except in compliance with | ||||
7 | # the License. You may obtain a copy of the License at: | ||||
8 | # | ||||
9 | # http://www.apache.org/licenses/LICENSE-2.0 | ||||
10 | # | ||||
11 | # Unless required by applicable law or agreed to in writing, software | ||||
12 | # distributed under the License is distributed on an "AS IS" BASIS, | ||||
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
14 | # See the License for the specific language governing permissions and | ||||
15 | # limitations under the License. | ||||
16 | # </@LICENSE> | ||||
17 | |||||
18 | package Mail::SpamAssassin::Locker::UnixNFSSafe; | ||||
19 | |||||
20 | 2 | 72µs | 2 | 89µs | # spent 74µs (58+16) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@20 which was called:
# once (58µs+16µs) by Mail::SpamAssassin::BEGIN@2 at line 20 # spent 74µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@20
# spent 16µs making 1 call to strict::import |
21 | 2 | 64µs | 2 | 104µs | # spent 63µs (23+40) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@21 which was called:
# once (23µs+40µs) by Mail::SpamAssassin::BEGIN@2 at line 21 # spent 63µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@21
# spent 40µs making 1 call to warnings::import |
22 | 2 | 69µs | 2 | 39µs | # spent 32µs (25+7) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@22 which was called:
# once (25µs+7µs) by Mail::SpamAssassin::BEGIN@2 at line 22 # spent 32µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@22
# spent 7µs making 1 call to bytes::import |
23 | 2 | 69µs | 2 | 178µs | # spent 107µs (35+72) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@23 which was called:
# once (35µs+72µs) by Mail::SpamAssassin::BEGIN@2 at line 23 # spent 107µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@23
# spent 72µs making 1 call to re::import |
24 | |||||
25 | 2 | 56µs | 1 | 16µs | # spent 16µs within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@25 which was called:
# once (16µs+0s) by Mail::SpamAssassin::BEGIN@2 at line 25 # spent 16µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@25 |
26 | 2 | 280µs | 1 | 3.86ms | # spent 3.86ms (992µs+2.87) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@26 which was called:
# once (992µs+2.87ms) by Mail::SpamAssassin::BEGIN@2 at line 26 # spent 3.86ms making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@26 |
27 | 2 | 71µs | 2 | 240µs | # spent 135µs (30+105) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@27 which was called:
# once (30µs+105µs) by Mail::SpamAssassin::BEGIN@2 at line 27 # spent 135µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@27
# spent 105µs making 1 call to Exporter::import |
28 | 2 | 69µs | 2 | 501µs | # spent 267µs (33+234) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@28 which was called:
# once (33µs+234µs) by Mail::SpamAssassin::BEGIN@2 at line 28 # spent 267µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@28
# spent 234µs making 1 call to Exporter::import |
29 | 2 | 53µs | 1 | 17µs | # spent 17µs within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@29 which was called:
# once (17µs+0s) by Mail::SpamAssassin::BEGIN@2 at line 29 # spent 17µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@29 |
30 | 2 | 71µs | 2 | 343µs | # spent 186µs (30+157) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@30 which was called:
# once (30µs+157µs) by Mail::SpamAssassin::BEGIN@2 at line 30 # spent 186µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@30
# spent 157µs making 1 call to Exporter::import |
31 | 2 | 77µs | 2 | 6.18ms | # spent 3.10ms (20µs+3.08) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@31 which was called:
# once (20µs+3.08ms) by Mail::SpamAssassin::BEGIN@2 at line 31 # spent 3.10ms making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@31
# spent 3.08ms making 1 call to Exporter::import |
32 | |||||
33 | 1 | 2µs | # spent 100µs (21+79) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@33 which was called:
# once (21µs+79µs) by Mail::SpamAssassin::BEGIN@2 at line 35 | ||
34 | @ISA | ||||
35 | 1 | 164µs | 2 | 180µs | }; # spent 100µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@33
# spent 79µs making 1 call to vars::import |
36 | |||||
37 | 1 | 15µs | @ISA = qw(Mail::SpamAssassin::Locker); | ||
38 | |||||
39 | ########################################################################### | ||||
40 | |||||
41 | # spent 65µs (31+34) within Mail::SpamAssassin::Locker::UnixNFSSafe::new which was called:
# once (31µs+34µs) by Mail::SpamAssassin::create_locker at line 3 of (eval 33)[Mail/SpamAssassin.pm:475] | ||||
42 | 1 | 2µs | my $class = shift; | ||
43 | 1 | 10µs | 1 | 34µs | my $self = $class->SUPER::new(@_); # spent 34µs making 1 call to Mail::SpamAssassin::Locker::new |
44 | 1 | 9µs | $self; | ||
45 | } | ||||
46 | |||||
47 | ########################################################################### | ||||
48 | # NFS-safe locking (I hope!): | ||||
49 | # Attempt to create a file lock, using NFS-safe locking techniques. | ||||
50 | # | ||||
51 | # Locking code adapted from code by Alexis Rosen <alexis@panix.com> | ||||
52 | # by Kelsey Cummings <kgc@sonic.net>, with mods by jm and quinlan | ||||
53 | # | ||||
54 | # A good implementation of Alexis' code, for reference, is here: | ||||
55 | # http://mail-index.netbsd.org/netbsd-bugs/1996/04/17/0002.html | ||||
56 | |||||
57 | 2 | 2.14ms | 2 | 414µs | # spent 220µs (26+194) within Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@57 which was called:
# once (26µs+194µs) by Mail::SpamAssassin::BEGIN@2 at line 57 # spent 220µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::BEGIN@57
# spent 194µs making 1 call to constant::import |
58 | |||||
59 | # spent 2.63ms (692µs+1.93) within Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock which was called 2 times, avg 1.31ms/call:
# once (438µs+1.22ms) by Mail::SpamAssassin::DBBasedAddrList::new_checker at line 71 of Mail/SpamAssassin/DBBasedAddrList.pm
# once (254µs+718µs) by Mail::SpamAssassin::BayesStore::DBM::tie_db_writable at line 280 of Mail/SpamAssassin/BayesStore/DBM.pm | ||||
60 | 2 | 7µs | my ($self, $path, $max_retries, $mode) = @_; | ||
61 | 2 | 5µs | my $is_locked = 0; | ||
62 | 2 | 4µs | my @stat; | ||
63 | |||||
64 | 2 | 4µs | $max_retries ||= 30; | ||
65 | 2 | 4µs | $mode ||= "0700"; | ||
66 | 2 | 8µs | $mode = (oct $mode) & 0666; | ||
67 | 2 | 18µs | 2 | 15µs | dbg ("locker: mode is $mode"); # spent 15µs making 2 calls to Mail::SpamAssassin::Logger::dbg, avg 8µs/call |
68 | |||||
69 | 2 | 7µs | my $lock_file = "$path.lock"; | ||
70 | 2 | 19µs | 2 | 340µs | my $hname = Mail::SpamAssassin::Util::fq_hostname(); # spent 340µs making 2 calls to Mail::SpamAssassin::Util::fq_hostname, avg 170µs/call |
71 | 2 | 29µs | 2 | 219µs | my $lock_tmp = Mail::SpamAssassin::Util::untaint_file_path # spent 219µs making 2 calls to Mail::SpamAssassin::Util::untaint_file_path, avg 110µs/call |
72 | ($path.".lock.".$hname.".".$$); | ||||
73 | |||||
74 | # keep this for unlocking | ||||
75 | 2 | 16µs | $self->{lock_tmp} = $lock_tmp; | ||
76 | |||||
77 | 2 | 28µs | 2 | 6µs | my $umask = umask(~$mode); # spent 6µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:umask, avg 3µs/call |
78 | 2 | 444µs | 2 | 416µs | if (!open(LTMP, ">$lock_tmp")) { # spent 416µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:open, avg 208µs/call |
79 | umask $umask; # just in case | ||||
80 | die "locker: safe_lock: cannot create tmp lockfile $lock_tmp for $lock_file: $!\n"; | ||||
81 | } | ||||
82 | 2 | 18µs | 2 | 4µs | umask $umask; # spent 4µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:umask, avg 2µs/call |
83 | 2 | 37µs | 2 | 280µs | autoflush LTMP 1; # spent 280µs making 2 calls to IO::Handle::autoflush, avg 140µs/call |
84 | 2 | 22µs | 2 | 15µs | dbg("locker: safe_lock: created $lock_tmp"); # spent 15µs making 2 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call |
85 | |||||
86 | 2 | 12µs | for (my $retries = 0; $retries < $max_retries; $retries++) { | ||
87 | 2 | 4µs | if ($retries > 0) { $self->jittery_one_second_sleep(); } | ||
88 | 2 | 149µs | 2 | 120µs | print LTMP "$hname.$$\n" or warn "Error writing to $lock_tmp: $!"; # spent 120µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:print, avg 60µs/call |
89 | 2 | 21µs | 2 | 14µs | dbg("locker: safe_lock: trying to get lock on $path with $retries retries"); # spent 14µs making 2 calls to Mail::SpamAssassin::Logger::dbg, avg 7µs/call |
90 | 2 | 161µs | 2 | 139µs | if (link($lock_tmp, $lock_file)) { # spent 139µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:link, avg 70µs/call |
91 | 2 | 17µs | 2 | 16µs | dbg("locker: safe_lock: link to $lock_file: link ok"); # spent 16µs making 2 calls to Mail::SpamAssassin::Logger::dbg, avg 8µs/call |
92 | 2 | 4µs | $is_locked = 1; | ||
93 | 2 | 7µs | last; | ||
94 | } | ||||
95 | # link _may_ return false even if the link _is_ created | ||||
96 | @stat = lstat($lock_tmp); | ||||
97 | @stat or warn "locker: error accessing $lock_tmp: $!"; | ||||
98 | if (defined $stat[3] && $stat[3] > 1) { | ||||
99 | dbg("locker: safe_lock: link to $lock_file: stat ok"); | ||||
100 | $is_locked = 1; | ||||
101 | last; | ||||
102 | } | ||||
103 | # check age of lockfile ctime | ||||
104 | my $now = ($#stat < 11 ? undef : $stat[10]); | ||||
105 | @stat = lstat($lock_file); | ||||
106 | @stat or warn "locker: error accessing $lock_file: $!"; | ||||
107 | my $lock_age = ($#stat < 11 ? undef : $stat[10]); | ||||
108 | if (defined($lock_age) && defined($now) && ($now - $lock_age) > LOCK_MAX_AGE) | ||||
109 | { | ||||
110 | # we got a stale lock, break it | ||||
111 | dbg("locker: safe_lock: breaking stale $lock_file: age=" . | ||||
112 | (defined $lock_age ? $lock_age : "undef") . " now=$now"); | ||||
113 | unlink($lock_file) | ||||
114 | or warn "locker: safe_lock: unlink of lock file $lock_file failed: $!\n"; | ||||
115 | } | ||||
116 | } | ||||
117 | |||||
118 | 2 | 39µs | 2 | 20µs | close LTMP or die "error closing $lock_tmp: $!"; # spent 20µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:close, avg 10µs/call |
119 | 2 | 305µs | 2 | 236µs | unlink($lock_tmp) # spent 236µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:unlink, avg 118µs/call |
120 | or warn "locker: safe_lock: unlink of temp lock $lock_tmp failed: $!\n"; | ||||
121 | |||||
122 | # record this for safe unlocking | ||||
123 | 2 | 10µs | if ($is_locked) { | ||
124 | 2 | 152µs | 2 | 95µs | @stat = lstat($lock_file); # spent 95µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:lstat, avg 48µs/call |
125 | 2 | 4µs | @stat or warn "locker: error accessing $lock_file: $!"; | ||
126 | 2 | 9µs | my $lock_ctime = ($#stat < 11 ? undef : $stat[10]); | ||
127 | |||||
128 | 2 | 11µs | $self->{lock_ctimes} ||= { }; | ||
129 | 2 | 11µs | $self->{lock_ctimes}->{$path} = $lock_ctime; | ||
130 | } | ||||
131 | |||||
132 | 2 | 36µs | return $is_locked; | ||
133 | } | ||||
134 | |||||
135 | ########################################################################### | ||||
136 | |||||
137 | # spent 5.64s (606µs+5.64) within Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock which was called 2 times, avg 2.82s/call:
# once (409µs+5.64s) by Mail::SpamAssassin::DBBasedAddrList::finish at line 113 of Mail/SpamAssassin/DBBasedAddrList.pm
# once (197µs+652µs) by Mail::SpamAssassin::BayesStore::DBM::untie_db at line 627 of Mail/SpamAssassin/BayesStore/DBM.pm | ||||
138 | 2 | 10µs | my ($self, $path) = @_; | ||
139 | |||||
140 | 2 | 13µs | my $lock_file = "$path.lock"; | ||
141 | 2 | 8µs | my $lock_tmp = $self->{lock_tmp}; | ||
142 | 2 | 5µs | if (!$lock_tmp) { | ||
143 | dbg("locker: safe_unlock: $path.lock never locked"); | ||||
144 | return; | ||||
145 | } | ||||
146 | |||||
147 | # 1. Build a temp file and stat that to get an idea of what the server | ||||
148 | # thinks the current time is (our_tmp.st_ctime). note: do not use time() | ||||
149 | # directly because the server's clock may be out of sync with the client's. | ||||
150 | |||||
151 | 2 | 5µs | my @stat_ourtmp; | ||
152 | 2 | 654µs | 2 | 610µs | if (!defined sysopen(LTMP, $lock_tmp, O_CREAT|O_WRONLY|O_EXCL, 0700)) { # spent 610µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:sysopen, avg 305µs/call |
153 | warn "locker: safe_unlock: failed to create lock tmpfile $lock_tmp: $!"; | ||||
154 | return; | ||||
155 | } else { | ||||
156 | 2 | 35µs | 2 | 325µs | autoflush LTMP 1; # spent 325µs making 2 calls to IO::Handle::autoflush, avg 163µs/call |
157 | 2 | 151µs | 2 | 128µs | print LTMP "\n" or warn "Error writing to $lock_tmp: $!"; # spent 128µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:print, avg 64µs/call |
158 | |||||
159 | 2 | 58µs | 2 | 18µs | if (!(@stat_ourtmp = stat(LTMP)) || (scalar(@stat_ourtmp) < 11)) { # spent 18µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:stat, avg 9µs/call |
160 | @stat_ourtmp or warn "locker: error accessing $lock_tmp: $!"; | ||||
161 | warn "locker: safe_unlock: failed to create lock tmpfile $lock_tmp"; | ||||
162 | close LTMP or die "error closing $lock_tmp: $!"; | ||||
163 | unlink($lock_tmp) | ||||
164 | or warn "locker: safe_lock: unlink of lock file failed: $!\n"; | ||||
165 | return; | ||||
166 | } | ||||
167 | } | ||||
168 | |||||
169 | 2 | 5µs | my $ourtmp_ctime = $stat_ourtmp[10]; # paranoia | ||
170 | 2 | 5µs | if (!defined $ourtmp_ctime) { | ||
171 | die "locker: safe_unlock: stat failed on $lock_tmp"; | ||||
172 | } | ||||
173 | |||||
174 | 2 | 44µs | 2 | 24µs | close LTMP or die "error closing $lock_tmp: $!"; # spent 24µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:close, avg 12µs/call |
175 | 2 | 304µs | 2 | 283µs | unlink($lock_tmp) # spent 283µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:unlink, avg 142µs/call |
176 | or warn "locker: safe_lock: unlink of lock file failed: $!\n"; | ||||
177 | |||||
178 | # 2. If the ctime hasn't been modified, unlink the file and return. If the | ||||
179 | # lock has expired, sleep the usual random interval before returning. If we | ||||
180 | # didn't sleep, there could be a race if the caller immediately tries to | ||||
181 | # relock the file. | ||||
182 | |||||
183 | 2 | 10µs | my $lock_ctime = $self->{lock_ctimes}->{$path}; | ||
184 | 2 | 4µs | if (!defined $lock_ctime) { | ||
185 | warn "locker: safe_unlock: no ctime recorded for $lock_file"; | ||||
186 | return; | ||||
187 | } | ||||
188 | |||||
189 | 2 | 68µs | 2 | 42µs | my @stat_lock = lstat($lock_file); # spent 42µs making 2 calls to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:lstat, avg 21µs/call |
190 | 2 | 62µs | @stat_lock or warn "locker: error accessing $lock_file: $!"; | ||
191 | |||||
192 | 2 | 5µs | my $now_ctime = $stat_lock[10]; | ||
193 | |||||
194 | 2 | 6µs | if (defined $now_ctime && $now_ctime == $lock_ctime) | ||
195 | { | ||||
196 | # things are good: the ctimes match so it was our lock | ||||
197 | 1 | 120µs | 1 | 110µs | unlink($lock_file) # spent 110µs making 1 call to Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:unlink |
198 | or warn "locker: safe_unlock: unlink failed: $lock_file\n"; | ||||
199 | 1 | 11µs | 1 | 8µs | dbg("locker: safe_unlock: unlink $lock_file"); # spent 8µs making 1 call to Mail::SpamAssassin::Logger::dbg |
200 | |||||
201 | 1 | 6µs | if ($ourtmp_ctime >= $lock_ctime + LOCK_MAX_AGE) { | ||
202 | # the lock has expired, so sleep a bit; use some randomness | ||||
203 | # to avoid race conditions. | ||||
204 | 1 | 10µs | 1 | 6µs | dbg("locker: safe_unlock: lock expired on $lock_file expired safely; sleeping"); # spent 6µs making 1 call to Mail::SpamAssassin::Logger::dbg |
205 | 2 | 49µs | my $i; for ($i = 0; $i < 5; $i++) { | ||
206 | 5 | 113µs | 5 | 5.64s | $self->jittery_one_second_sleep(); # spent 5.64s making 5 calls to Mail::SpamAssassin::Locker::jittery_one_second_sleep, avg 1.13s/call |
207 | } | ||||
208 | } | ||||
209 | 1 | 40µs | return; | ||
210 | } | ||||
211 | |||||
212 | # 4. Either ctime has been modified, or the entire lock file is missing. | ||||
213 | # If the lock should still be ours, based on the ctime of the temp | ||||
214 | # file, warn it was stolen. If not, then our lock is expired and | ||||
215 | # someone else has grabbed the file, so warn it was lost. | ||||
216 | 1 | 16µs | if ($ourtmp_ctime < $lock_ctime + LOCK_MAX_AGE) { | ||
217 | warn "locker: safe_unlock: lock on $lock_file was stolen"; | ||||
218 | } else { | ||||
219 | 1 | 10µs | warn "locker: safe_unlock: lock on $lock_file was lost due to expiry"; | ||
220 | } | ||||
221 | } | ||||
222 | |||||
223 | ########################################################################### | ||||
224 | |||||
225 | sub refresh_lock { | ||||
226 | my($self, $path) = @_; | ||||
227 | |||||
228 | return unless $path; | ||||
229 | |||||
230 | # this could arguably read the lock and make sure the same process | ||||
231 | # owns it, but this shouldn't, in theory, be an issue. | ||||
232 | # TODO: in NFS, it definitely may be one :( | ||||
233 | |||||
234 | my $lock_file = "$path.lock"; | ||||
235 | utime time, time, $lock_file; | ||||
236 | |||||
237 | # update the lock_ctimes entry | ||||
238 | my @stat = lstat($lock_file); | ||||
239 | @stat or warn "locker: error accessing $lock_file: $!"; | ||||
240 | |||||
241 | my $lock_ctime = ($#stat < 11 ? undef : $stat[10]); | ||||
242 | $self->{lock_ctimes}->{$path} = $lock_ctime; | ||||
243 | |||||
244 | dbg("locker: refresh_lock: refresh $path.lock"); | ||||
245 | } | ||||
246 | |||||
247 | ########################################################################### | ||||
248 | |||||
249 | 1 | 8µs | 1; | ||
# spent 44µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:close which was called 4 times, avg 11µs/call:
# 2 times (24µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 174, avg 12µs/call
# 2 times (20µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 118, avg 10µs/call | |||||
# spent 139µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:link which was called 2 times, avg 70µs/call:
# 2 times (139µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 90, avg 70µs/call | |||||
# spent 137µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:lstat which was called 4 times, avg 34µs/call:
# 2 times (95µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 124, avg 48µs/call
# 2 times (42µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 189, avg 21µs/call | |||||
# spent 416µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:open which was called 2 times, avg 208µs/call:
# 2 times (416µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 78, avg 208µs/call | |||||
# spent 247µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:print which was called 4 times, avg 62µs/call:
# 2 times (128µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 157, avg 64µs/call
# 2 times (120µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 88, avg 60µs/call | |||||
# spent 18µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:stat which was called 2 times, avg 9µs/call:
# 2 times (18µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 159, avg 9µs/call | |||||
# spent 610µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:sysopen which was called 2 times, avg 305µs/call:
# 2 times (610µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 152, avg 305µs/call | |||||
# spent 10µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:umask which was called 4 times, avg 3µs/call:
# 2 times (6µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 77, avg 3µs/call
# 2 times (4µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 82, avg 2µs/call | |||||
# spent 629µs within Mail::SpamAssassin::Locker::UnixNFSSafe::CORE:unlink which was called 5 times, avg 126µs/call:
# 2 times (283µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 175, avg 142µs/call
# 2 times (236µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_lock at line 119, avg 118µs/call
# once (110µs+0s) by Mail::SpamAssassin::Locker::UnixNFSSafe::safe_unlock at line 197 |