1AnyEvent::Impl::POE(3)User Contributed Perl DocumentationAnyEvent::Impl::POE(3)
2
3
4
6 AnyEvent::Impl::POE - AnyEvent adaptor for POE
7
9 use AnyEvent;
10 use POE;
11
12 # this module gets loaded automatically as required
13
15 This module provides transparent support for AnyEvent. You don't have
16 to do anything to make POE work with AnyEvent except by loading POE
17 before creating the first AnyEvent watcher. There are some cases where
18 POE will issue spurious (and non-suppressible) warnings. These can be
19 avoided by loading AnyEvent::Impl::POE before loading any other modules
20 using POE and AnyEvent, i.e. in your main program.
21
22 AnyEvent::Impl::POE will output some spurious message how to work
23 around POE's spurious messages when it detects these cases.
24
25 Unfortunately, POE isn't generic enough to implement a fully working
26 AnyEvent backend: POE is too badly designed, too badly documented and
27 too badly implemented.
28
29 Here are the details, and what it means to you if you want to be
30 interoperable with POE:
31
32 Weird messages
33 If you only use "run_one_timeslice" (as AnyEvent has to for its
34 condition variables), POE will print an ugly, unsuppressible,
35 message at program exit:
36
37 Sessions were started, but POE::Kernel's run() method was never...
38
39 The message is correct, the question is why POE prints it in the
40 first place in a correct program (this is not a singular case
41 though).
42
43 AnyEvent consequently patches the POE kernel so it thinks it
44 already ran. Other workarounds, even the one cited in the POE
45 documentation itself, have serious side effects, such as throwing
46 away events.
47
48 The author of POE verified that this is indeed true, and has no
49 plans to change this.
50
51 POE has other weird messages, and sometimes weird behaviour, for
52 example, it doesn't support overloaded code references as callbacks
53 for no apparent reason.
54
55 One POE session per Event
56 AnyEvent has to create one POE::Session per event watcher, which is
57 immensely slow and makes watchers very large. The reason for this
58 is lacking lifetime management (mostly undocumented, too). Without
59 one session/watcher it is not possible to easily keep the kernel
60 from running endlessly.
61
62 This is not just a problem with the way AnyEvent has to interact
63 with POE, but is a principal issue with POEs lifetime management
64 (namely that stopping the kernel stops sessions, but AnyEvent has
65 no control over who and when the kernel starts or stops w.r.t.
66 AnyEvent watcher creation/destruction).
67
68 From benchmark data it is not clear that session creation is that
69 costly, though - the real inefficiencies with POE seem to come from
70 other sources, such as event handling.
71
72 One watcher per fd/event combo
73 POE, of course, suffers from the same bug as Tk and some other
74 badly designed event models in that it doesn't support multiple
75 watchers per fd/poll combo. The workaround is the same as with Tk:
76 AnyEvent::Impl::POE creates a separate file descriptor to hand to
77 POE, which isn't fast and certainly not nice to your resources.
78
79 Of course, without the workaround, POE also prints ugly messages
80 again that say the program *might* be buggy.
81
82 While this is not good to performance, at least regarding speed,
83 with a modern Linux kernel, the overhead is actually quite small.
84
85 Timing deficiencies
86 POE manages to not have a function that returns the current time.
87 This is extremely problematic, as POE can use different time
88 functions, which can differ by more than a second - and user code
89 is left guessing which one is used.
90
91 In addition, most timer functions in POE want an absolute
92 timestamp, which is hard to create if all you have is a relative
93 time and no function to return the "current time".
94
95 And of course POE doesn't handle time jumps at all (not even when
96 using an event loop that happens to do that, such as EV, as it does
97 its own unoptimised timer management).
98
99 AnyEvent works around the unavailability of the current time using
100 relative timers exclusively, in the hope that POE gets it right at
101 least internally.
102
103 Lack of defined event ordering
104 POE cannot guarantee the order of callback invocation for timers,
105 and usually gets it wrong. That is, if you have two timers, one
106 timing out after another (all else being equal), the callbacks
107 might be called in reverse order.
108
109 How one manages to even implement stuff that way escapes me.
110
111 Child watchers
112 POE offers child watchers - which is a laudable thing, as few event
113 loops do. Unfortunately, they cannot even implement AnyEvent's
114 simple child watchers: they are not generic enough (the POE
115 implementation isn't even generic enough to let properly designed
116 back-end use their native child watcher instead - it insist on
117 doing it itself the broken way).
118
119 Unfortunately, POE's child handling is inherently racy: if the
120 child exits before the handler is created (because e.g. it crashes
121 or simply is quick about it), then current versions of POE (1.352)
122 will never invoke the child watcher, and there is nothing that can
123 be done about it. Older versions of POE only delayed in this case.
124 The reason is that POE first checks if the child has already
125 exited, and then installs the signal handler - aa classical race.
126
127 Your only hope is for the fork'ed process to not exit too quickly,
128 in which case everything happens to work.
129
130 Of course, whenever POE reaps an unrelated child it will also
131 output a message for it that you cannot suppress (which shouldn't
132 be too surprising at this point). Very professional.
133
134 As a workaround, AnyEvent::Impl::POE will take advantage of
135 undocumented behaviour in POE::Kernel to catch the status of all
136 child processes, but it cannot guarantee delivery.
137
138 How one manages to have such a glaring bug in an event loop after
139 ten years of development escapes me.
140
141 (There are more annoying bugs, for example, POE runs "waitpid"
142 unconditionally at finaliser time, so your program will hang until
143 all child processes have exited.)
144
145 Documentation quality
146 At the time of this writing, POE was in its tenth year. Still, its
147 documentation is extremely lacking, making it impossible to
148 implement stuff as trivial as AnyEvent watchers without having to
149 resort to undocumented behaviour or features.
150
151 For example, the POE::Kernel manpage has nine occurrences of the
152 word TODO with an explanation of whats missing. In general, the POE
153 man pages are littered with comments like "section not yet
154 written".
155
156 Some other gems:
157
158 This allows many object methods to also be package methods.
159
160 This is nice, but since it doesn't document which methods these
161 are, this is utterly useless information.
162
163 Terminal signals will kill sessions if they are not handled by a
164 "sig_handled"() call. The OS signals that usually kill or dump a
165 process are considered terminal in POE, but they never trigger a
166 coredump. These are: HUP, INT, QUIT and TERM.
167
168 Although AnyEvent calls "sig_handled", removing it has no apparent
169 effects on POE handling SIGINT.
170
171 refcount_increment SESSION_ID, COUNTER_NAME
172
173 Nowhere is explained which COUNTER_NAMEs are valid and which aren't
174 - not all scalars (or even strings) are valid counter names. Take
175 your guess, failure is of course completely silent. I found this
176 out the hard way, as the first name I came up with was silently
177 ignored.
178
179 get_next_event_time() returns the time the next event is due, in a form
180 compatible with the UNIX time() function.
181
182 And surely, one would hope that POE supports sub-second accuracy as
183 documented elsewhere, unlike the explanation above implies. Yet:
184
185 POE::Kernel timers support subsecond accuracy, but don’t expect too
186 much here. Perl is not the right language for realtime programming.
187
188 ... of course, Perl is not the right language to expect sub-second
189 accuracy - the manpage author must hate Perl to spread so much FUD
190 in so little space. The Deliantra game server logs with
191 100µs-accuracy because Perl is fast enough to require this, and is
192 still able to deliver map updates with little jitter at exactly the
193 right time. It does not, however, use POE.
194
195 Furthermore, since the Kernel keeps track of everything sessions do, it
196 knows when a session has run out of tasks to perform.
197
198 This is impossible - how does the kernel know that a session is no
199 longer watching for some (external) event (e.g. by some other
200 session)? It cannot, and therefore this is wrong - but you would be
201 hard pressed to find out how to work around this and tell the
202 kernel manually about such events.
203
204 It gets worse, though - the notion of "task" or "resource",
205 although used throughout the documentation, is not defined in a
206 usable way. For example, waiting for a timeout is considered to be
207 a task, waiting for a signal is not (a session that only waits for
208 a signal is considered finished and gets removed). The user is left
209 guessing when waiting for an event counts as task and when not (in
210 fact, the issue with signals is mentioned in passing in a section
211 about child watchers and directly contradicts earlier parts in that
212 document).
213
214 One could go on endlessly - ten years, no usable documentation.
215
216 It is likely that differences between documentation, or the one or
217 two things I had to guess, cause unanticipated problems with this
218 adaptor.
219
220 Fragile and inconsistent API
221 The POE API is extremely inconsistent - sometimes you have to pass
222 a session argument, sometimes it gets ignored, sometimes a session-
223 specific method must not use a session argument.
224
225 Error handling is sub-standard as well: even for programming
226 mistakes, POE does not "croak" but, in most cases, just sets $! or
227 simply does nothing at all, leading to fragile programs.
228
229 Sometimes registering a handler uses the "eventname, parameter"
230 ordering (timeouts), sometimes it is "parameter, eventname"
231 (signals). There is little consistency overall.
232
233 Lack of knowledge
234 The IO::Poll event loop provides an alternative that theoretically
235 scales better than select().
236
237 The IO::Poll "event loop" (who in his right mind would call that an
238 event loop) of course scales about identically (sometimes it is a
239 bit faster, sometimes a bit slower) to select in theory, and also
240 in practise, of course, as both are O(n) in the number of file
241 descriptors, which is rather bad.
242
243 This is just one place where it gets obvious how little the author
244 of the POE manpage understands.
245
246 No idle events
247 The POE-recommended workaround to this is apparently to use "fork".
248 Consequently, idle watchers will have to be emulated by AnyEvent.
249
250 Questionable maintainer behaviour
251 The author of POE is known to fabricate statements and post these
252 to public mailinglists - apparently, spreading FUD about competing
253 (in his eyes) projects or their maintainers is acceptable to him.
254
255 This has (I believe) zero effects on the quality or usefulness of
256 his code, but it does completely undermine his trustworthyness - so
257 don't blindly believe anything he says, he might have just made it
258 up to suit his needs (benchmark results, the names of my ten wifes,
259 the length of my penis, etc. etc.). When in doubt, double-check -
260 not just him, anybody actually.
261
262 Example:
263 <http://www.nntp.perl.org/group/perl.perl5.porters/2012/01/msg182141.html>.
264 I challenged him in that thread to provide evidence for his
265 statement by giving at least two examples, but of course since he
266 just made it up, he couldn't provide any evidence.
267
268 On the good side, AnyEvent allows you to write your modules in a 100%
269 POE-compatible way (bug-for-bug compatible even), without forcing your
270 module to use POE - it is still open to better event models, of which
271 there are plenty.
272
273 Oh, and one other positive thing:
274
275 RUNNING_IN_HELL
276
277 POE knows about the nature of the beast!
278
280 AnyEvent, POE.
281
283 Marc Lehmann <schmorp@schmorp.de>
284 http://anyevent.schmorp.de
285
286
287
288perl v5.34.0 2022-01-20 AnyEvent::Impl::POE(3)