ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent/lib/AnyEvent/Strict.pm
Revision: 1.38
Committed: Tue Mar 27 16:21:11 2012 UTC (12 years, 2 months ago) by root
Branch: MAIN
Changes since 1.37: +2 -2 lines
Log Message:
put 1; to the end of .pm files

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(croak);
28 use Errno ();
29 use POSIX ();
30
31 use AnyEvent (); BEGIN { AnyEvent::common_sense }
32
33 AnyEvent::_isa_hook 1 => "AnyEvent::Strict", 1;
34
35 BEGIN {
36 if (defined &Internals::SvREADONLY) {
37 # readonly available (at least 5.8.9+, working better in 5.10.1+)
38 *wrap = sub {
39 my $cb = shift;
40
41 sub {
42 local $_;
43 Internals::SvREADONLY $_, 1;
44 &$cb;
45 }
46 };
47 } else {
48 # or not :/
49 my $magic = []; # a unique magic value
50
51 *wrap = sub {
52 my $cb = shift;
53
54 sub {
55 local $_ = $magic;
56
57 &$cb;
58
59 if (!ref $_ || $_ != $magic) {
60 require AnyEvent::Debug;
61 die "callback $cb (" . AnyEvent::Debug::cb2str ($cb) . ") modified \$_ without restoring it.\n";
62 }
63 }
64 };
65 }
66 }
67
68 our (@FD_INUSE, $FD_I);
69 our $FD_CHECK_W = AE::timer 4, 4, sub {
70 my $cnt = (@FD_INUSE < 100 * 10 ? int @FD_INUSE * 0.1 : 100) || 10;
71
72 if ($FD_I <= 0) {
73 #pop @FD_INUSE while @FD_INUSE && !$FD_INUSE[-1];
74 $FD_I = @FD_INUSE
75 or return; # empty
76 }
77
78 $cnt = $FD_I if $cnt > $FD_I;
79
80 eval {
81 do {
82 !$FD_INUSE[--$FD_I]
83 or (POSIX::lseek $FD_I, 0, 1) != -1
84 or $! != Errno::EBADF
85 or die;
86 } while --$cnt;
87 1
88 } or AE::log crit => "file descriptor $FD_I registered with AnyEvent but prematurely closed, event loop might malfunction.\n";
89 };
90
91 sub io {
92 my $class = shift;
93 my (%arg, $fh, $cb, $fd) = @_;
94
95 ref $arg{cb}
96 or croak "AnyEvent->io called with illegal cb argument '$arg{cb}'";
97 $cb = wrap delete $arg{cb};
98
99 $arg{poll} =~ /^[rw]$/
100 or croak "AnyEvent->io called with illegal poll argument '$arg{poll}'";
101
102 $fh = delete $arg{fh};
103
104 if ($fh =~ /^\s*\d+\s*$/) {
105 $fd = $fh;
106 $fh = AnyEvent::_dupfh $arg{poll}, $fh;
107 } else {
108 defined eval { $fd = fileno $fh }
109 or croak "AnyEvent->io called with illegal fh argument '$fh'";
110 }
111
112 -f $fh
113 and croak "AnyEvent->io called with fh argument pointing to a file";
114
115 delete $arg{poll};
116
117 croak "AnyEvent->io called with unsupported parameter(s) " . join ", ", keys %arg
118 if keys %arg;
119
120 ++$FD_INUSE[$fd];
121
122 bless [
123 $fd,
124 $class->SUPER::io (@_, cb => $cb)
125 ], "AnyEvent::Strict::io";
126 }
127
128 sub AnyEvent::Strict::io::DESTROY {
129 --$FD_INUSE[$_[0][0]];
130 }
131
132 sub timer {
133 my $class = shift;
134 my %arg = @_;
135
136 ref $arg{cb}
137 or croak "AnyEvent->timer called with illegal cb argument '$arg{cb}'";
138 my $cb = wrap delete $arg{cb};
139
140 exists $arg{after}
141 or croak "AnyEvent->timer called without mandatory 'after' parameter";
142 delete $arg{after};
143
144 !$arg{interval} or $arg{interval} > 0
145 or croak "AnyEvent->timer called with illegal interval argument '$arg{interval}'";
146 delete $arg{interval};
147
148 croak "AnyEvent->timer called with unsupported parameter(s) " . join ", ", keys %arg
149 if keys %arg;
150
151 $class->SUPER::timer (@_, cb => $cb)
152 }
153
154 sub signal {
155 my $class = shift;
156 my %arg = @_;
157
158 ref $arg{cb}
159 or croak "AnyEvent->signal called with illegal cb argument '$arg{cb}'";
160 my $cb = wrap delete $arg{cb};
161
162 defined AnyEvent::Base::sig2num $arg{signal} and $arg{signal} == 0
163 or croak "AnyEvent->signal called with illegal signal name '$arg{signal}'";
164 delete $arg{signal};
165
166 croak "AnyEvent->signal called with unsupported parameter(s) " . join ", ", keys %arg
167 if keys %arg;
168
169 $class->SUPER::signal (@_, cb => $cb)
170 }
171
172 sub child {
173 my $class = shift;
174 my %arg = @_;
175
176 ref $arg{cb}
177 or croak "AnyEvent->child called with illegal cb argument '$arg{cb}'";
178 my $cb = wrap delete $arg{cb};
179
180 $arg{pid} =~ /^-?\d+$/
181 or croak "AnyEvent->child called with malformed pid value '$arg{pid}'";
182 delete $arg{pid};
183
184 croak "AnyEvent->child called with unsupported parameter(s) " . join ", ", keys %arg
185 if keys %arg;
186
187 $class->SUPER::child (@_, cb => $cb)
188 }
189
190 sub idle {
191 my $class = shift;
192 my %arg = @_;
193
194 ref $arg{cb}
195 or croak "AnyEvent->idle called with illegal cb argument '$arg{cb}'";
196 my $cb = wrap delete $arg{cb};
197
198 croak "AnyEvent->idle called with unsupported parameter(s) " . join ", ", keys %arg
199 if keys %arg;
200
201 $class->SUPER::idle (@_, cb => $cb)
202 }
203
204 sub condvar {
205 my $class = shift;
206 my %arg = @_;
207
208 !exists $arg{cb} or ref $arg{cb}
209 or croak "AnyEvent->condvar called with illegal cb argument '$arg{cb}'";
210 my @cb = exists $arg{cb} ? (cb => wrap delete $arg{cb}) : ();
211
212 croak "AnyEvent->condvar called with unsupported parameter(s) " . join ", ", keys %arg
213 if keys %arg;
214
215 $class->SUPER::condvar (@cb);
216 }
217
218 sub time {
219 my $class = shift;
220
221 @_
222 and croak "AnyEvent->time wrongly called with paramaters";
223
224 $class->SUPER::time (@_)
225 }
226
227 sub now {
228 my $class = shift;
229
230 @_
231 and croak "AnyEvent->now wrongly called with paramaters";
232
233 $class->SUPER::now (@_)
234 }
235
236 =head1 AUTHOR
237
238 Marc Lehmann <schmorp@schmorp.de>
239 http://home.schmorp.de/
240
241 =cut
242
243 1
244