ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Strict.pm
Revision: 1.44
Committed: Sat Jul 7 14:03:05 2018 UTC (6 years, 5 months ago) by root
Branch: MAIN
CVS Tags: rel-7_16, rel-7_15, HEAD
Changes since 1.43: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 NAME
2
3 AnyEvent::Strict - force strict mode on for the whole process
4
5 =head1 SYNOPSIS
6
7 use AnyEvent::Strict;
8 # strict mode now switched on
9
10 =head1 DESCRIPTION
11
12 This module implements AnyEvent's strict mode.
13
14 Loading it makes AnyEvent check all arguments to AnyEvent-methods, at the
15 expense of being slower (often the argument checking takes longer than the
16 actual function). It also wraps all callbacks to check for modifications
17 of C<$_>, which indicates a programming bug inside the watcher callback.
18
19 Normally, you don't load this module yourself but instead use it
20 indirectly via the C<PERL_ANYEVENT_STRICT> environment variable (see
21 L<AnyEvent>). However, this module can be loaded manually at any time.
22
23 =cut
24
25 package AnyEvent::Strict;
26
27 use Carp qw(confess);
28 use Errno ();
29 use POSIX ();
30
31 $Carp::Internal{AE} = 1;
32 $Carp::Internal{AnyEvent::Strict} = 1;
33
34 use AnyEvent (); BEGIN { AnyEvent::common_sense }
35
36 AnyEvent::_isa_hook 1 => "AnyEvent::Strict", 1;
37
38 BEGIN {
39 if (defined &Internals::SvREADONLY) {
40 # readonly available (at least 5.8.9+, working better in 5.10.1+)
41 *wrap = sub {
42 my $cb = shift;
43
44 sub {
45 local $_;
46 Internals::SvREADONLY $_, 1;
47 &$cb;
48 }
49 };
50 } else {
51 # or not :/
52 my $magic = []; # a unique magic value
53
54 *wrap = sub {
55 my $cb = shift;
56
57 sub {
58 local $_ = $magic;
59
60 &$cb;
61
62 if (!ref $_ || $_ != $magic) {
63 require AnyEvent::Debug;
64 die "callback $cb (" . AnyEvent::Debug::cb2str ($cb) . ") modified \$_ without restoring it.\n";
65 }
66 }
67 };
68 }
69 }
70
71 our (@FD_INUSE, $FD_I);
72 our $FD_CHECK_W = AE::timer 4, 4, sub {
73 my $cnt = (@FD_INUSE < 100 * 10 ? int @FD_INUSE * 0.1 : 100) || 10;
74
75 if ($FD_I <= 0) {
76 #pop @FD_INUSE while @FD_INUSE && !$FD_INUSE[-1];
77 $FD_I = @FD_INUSE
78 or return; # empty
79 }
80
81 $cnt = $FD_I if $cnt > $FD_I;
82
83 eval {
84 do {
85 !$FD_INUSE[--$FD_I]
86 or (POSIX::lseek $FD_I, 0, 1) != -1
87 or $! != Errno::EBADF
88 or die;
89 } while --$cnt;
90 1
91 } or AE::log crit => "File descriptor $FD_I registered with AnyEvent but prematurely closed, event loop might malfunction.";
92 };
93
94 sub io {
95 my $class = shift;
96 my (%arg, $fh, $cb, $fd) = @_;
97
98 ref $arg{cb}
99 or confess "AnyEvent->io called with illegal cb argument '$arg{cb}'";
100 $cb = wrap delete $arg{cb};
101
102 $arg{poll} =~ /^[rw]$/
103 or confess "AnyEvent->io called with illegal poll argument '$arg{poll}'";
104
105 $fh = delete $arg{fh};
106
107 if ($fh =~ /^\s*\d+\s*$/) {
108 $fd = $fh;
109 ($fh) = AnyEvent::_dupfh $arg{poll}, $fh;
110 } else {
111 defined eval { $fd = fileno $fh }
112 or confess "AnyEvent->io called with illegal fh argument '$fh'";
113 }
114
115 -f $fh
116 and confess "AnyEvent->io called with fh argument pointing to a file";
117
118 delete $arg{poll};
119
120 confess "AnyEvent->io called with unsupported parameter(s) " . join ", ", keys %arg
121 if keys %arg;
122
123 ++$FD_INUSE[$fd];
124
125 bless [
126 $fd,
127 $class->SUPER::io (@_, cb => $cb)
128 ], "AnyEvent::Strict::io";
129 }
130
131 sub AnyEvent::Strict::io::DESTROY {
132 --$FD_INUSE[$_[0][0]];
133 }
134
135 sub timer {
136 my $class = shift;
137 my %arg = @_;
138
139 ref $arg{cb}
140 or confess "AnyEvent->timer called with illegal cb argument '$arg{cb}'";
141 my $cb = wrap delete $arg{cb};
142
143 exists $arg{after}
144 or confess "AnyEvent->timer called without mandatory 'after' parameter";
145 delete $arg{after};
146
147 !$arg{interval} or $arg{interval} > 0
148 or confess "AnyEvent->timer called with illegal interval argument '$arg{interval}'";
149 delete $arg{interval};
150
151 confess "AnyEvent->timer called with unsupported parameter(s) " . join ", ", keys %arg
152 if keys %arg;
153
154 $class->SUPER::timer (@_, cb => $cb)
155 }
156
157 sub signal {
158 my $class = shift;
159 my %arg = @_;
160
161 ref $arg{cb}
162 or confess "AnyEvent->signal called with illegal cb argument '$arg{cb}'";
163 my $cb = wrap delete $arg{cb};
164
165 defined AnyEvent::Base::sig2num $arg{signal} and $arg{signal} == 0
166 or confess "AnyEvent->signal called with illegal signal name '$arg{signal}'";
167 delete $arg{signal};
168
169 confess "AnyEvent->signal called with unsupported parameter(s) " . join ", ", keys %arg
170 if keys %arg;
171
172 $class->SUPER::signal (@_, cb => $cb)
173 }
174
175 sub child {
176 my $class = shift;
177 my %arg = @_;
178
179 ref $arg{cb}
180 or confess "AnyEvent->child called with illegal cb argument '$arg{cb}'";
181 my $cb = wrap delete $arg{cb};
182
183 $arg{pid} =~ /^-?\d+$/
184 or confess "AnyEvent->child called with malformed pid value '$arg{pid}'";
185 delete $arg{pid};
186
187 confess "AnyEvent->child called with unsupported parameter(s) " . join ", ", keys %arg
188 if keys %arg;
189
190 $class->SUPER::child (@_, cb => $cb)
191 }
192
193 sub idle {
194 my $class = shift;
195 my %arg = @_;
196
197 ref $arg{cb}
198 or confess "AnyEvent->idle called with illegal cb argument '$arg{cb}'";
199 my $cb = wrap delete $arg{cb};
200
201 confess "AnyEvent->idle called with unsupported parameter(s) " . join ", ", keys %arg
202 if keys %arg;
203
204 $class->SUPER::idle (@_, cb => $cb)
205 }
206
207 sub condvar {
208 my $class = shift;
209 my %arg = @_;
210
211 !exists $arg{cb} or ref $arg{cb}
212 or confess "AnyEvent->condvar called with illegal cb argument '$arg{cb}'";
213 my @cb = exists $arg{cb} ? (cb => wrap delete $arg{cb}) : ();
214
215 confess "AnyEvent->condvar called with unsupported parameter(s) " . join ", ", keys %arg
216 if keys %arg;
217
218 $class->SUPER::condvar (@cb);
219 }
220
221 sub time {
222 my $class = shift;
223
224 @_
225 and confess "AnyEvent->time wrongly called with paramaters";
226
227 $class->SUPER::time (@_)
228 }
229
230 sub now {
231 my $class = shift;
232
233 @_
234 and confess "AnyEvent->now wrongly called with paramaters";
235
236 $class->SUPER::now (@_)
237 }
238
239 =head1 AUTHOR
240
241 Marc Lehmann <schmorp@schmorp.de>
242 http://anyevent.schmorp.de
243
244 =cut
245
246 1
247