/src/php-src/ext/standard/io_poll.c
Line | Count | Source |
1 | | /* |
2 | | +----------------------------------------------------------------------+ |
3 | | | Copyright (c) The PHP Group | |
4 | | +----------------------------------------------------------------------+ |
5 | | | This source file is subject to the Modified BSD License that is | |
6 | | | bundled with this package in the file LICENSE, and is available | |
7 | | | through the World Wide Web at <https://www.php.net/license/>. | |
8 | | | | |
9 | | | SPDX-License-Identifier: BSD-3-Clause | |
10 | | +----------------------------------------------------------------------+ |
11 | | | Author: Jakub Zelenka <bukka@php.net> | |
12 | | +----------------------------------------------------------------------+ |
13 | | */ |
14 | | |
15 | | #include "php.h" |
16 | | #include "zend_enum.h" |
17 | | #include "zend_exceptions.h" |
18 | | #include "php_network.h" |
19 | | #include "php_poll.h" |
20 | | #include "io_poll_arginfo.h" |
21 | | #include "io_poll_decl.h" |
22 | | |
23 | | /* Class entries */ |
24 | | static zend_class_entry *php_io_poll_backend_class_entry; |
25 | | static zend_class_entry *php_io_poll_event_class_entry; |
26 | | static zend_class_entry *php_io_poll_context_class_entry; |
27 | | static zend_class_entry *php_io_poll_watcher_class_entry; |
28 | | static zend_class_entry *php_io_poll_handle_class_entry; |
29 | | static zend_class_entry *php_io_exception_class_entry; |
30 | | static zend_class_entry *php_io_poll_exception_class_entry; |
31 | | static zend_class_entry *php_io_poll_failed_backend_unavailable_class_entry; |
32 | | static zend_class_entry *php_io_poll_failed_operation_class_entry; |
33 | | static zend_class_entry *php_io_poll_failed_context_init_class_entry; |
34 | | static zend_class_entry *php_io_poll_failed_handle_add_class_entry; |
35 | | static zend_class_entry *php_io_poll_failed_watcher_mod_class_entry; |
36 | | static zend_class_entry *php_io_poll_failed_wait_class_entry; |
37 | | static zend_class_entry *php_io_poll_inactive_watcher_class_entry; |
38 | | static zend_class_entry *php_io_poll_handle_already_watched_class_entry; |
39 | | static zend_class_entry *php_io_poll_invalid_handle_class_entry; |
40 | | static zend_class_entry *php_stream_poll_handle_class_entry; |
41 | | |
42 | | /* Object handlers */ |
43 | | static zend_object_handlers php_io_poll_context_object_handlers; |
44 | | static zend_object_handlers php_io_poll_watcher_object_handlers; |
45 | | static zend_object_handlers php_io_poll_handle_object_handlers; |
46 | | |
47 | | typedef struct php_io_poll_context_object php_io_poll_context_object; |
48 | | |
49 | | /* Watcher object structure */ |
50 | | typedef struct php_io_poll_watcher_object { |
51 | | php_poll_handle_object *handle; |
52 | | uint32_t watched_events; |
53 | | uint32_t triggered_events; |
54 | | zval data; |
55 | | bool active; |
56 | | php_io_poll_context_object *context; /* Back reference to Context object */ |
57 | | zend_object std; |
58 | | } php_io_poll_watcher_object; |
59 | | |
60 | | /* Context object structure */ |
61 | | struct php_io_poll_context_object { |
62 | | php_poll_ctx *ctx; |
63 | | HashTable *watchers; /* Maps handle pointer -> watcher object */ |
64 | | zend_object std; |
65 | | }; |
66 | | |
67 | | /* Stream poll handle specific data */ |
68 | | typedef struct php_stream_poll_handle_data { |
69 | | php_stream *stream; |
70 | | zend_resource *res; |
71 | | } php_stream_poll_handle_data; |
72 | | |
73 | | /* Accessor macros */ |
74 | 10 | #define PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(_obj) ZEND_CONTAINER_OF(_obj, php_io_poll_context_object, std) |
75 | | |
76 | 5 | #define PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(_obj) ZEND_CONTAINER_OF(_obj, php_io_poll_watcher_object, std) |
77 | | |
78 | 0 | #define PHP_POLL_WATCHER_OBJ_FROM_ZV(_zv) PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(Z_OBJ_P(_zv)) |
79 | 5 | #define PHP_POLL_CONTEXT_OBJ_FROM_ZV(_zv) PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(Z_OBJ_P(_zv)) |
80 | | |
81 | | /* Helper to throw failed operation exceptions with error code */ |
82 | | static inline void php_io_poll_throw_failed_operation( |
83 | | zend_class_entry *ce, const char *message, php_poll_error error) |
84 | 0 | { |
85 | 0 | zend_throw_exception(ce, message, (zend_long) error); |
86 | 0 | } |
87 | | |
88 | | /* Event enum to bit mask mapping */ |
89 | | static uint32_t php_io_poll_event_enum_to_bit(zend_object *event_enum) |
90 | 0 | { |
91 | 0 | return 1 << (zend_enum_fetch_case_id(event_enum) - 1); |
92 | 0 | } |
93 | | |
94 | | static uint32_t php_io_poll_event_enums_to_events(zval *event_enums) |
95 | 0 | { |
96 | 0 | HashTable *ht; |
97 | 0 | uint32_t events = 0; |
98 | |
|
99 | 0 | if (Z_TYPE_P(event_enums) != IS_ARRAY) { |
100 | 0 | return 0; |
101 | 0 | } |
102 | | |
103 | 0 | ht = Z_ARRVAL_P(event_enums); |
104 | |
|
105 | 0 | ZEND_HASH_FOREACH_VAL(ht, zval *entry) { |
106 | 0 | if (Z_TYPE_P(entry) != IS_OBJECT |
107 | 0 | || !instanceof_function(Z_OBJCE_P(entry), php_io_poll_event_class_entry)) { |
108 | 0 | return 0; |
109 | 0 | } |
110 | 0 | events |= php_io_poll_event_enum_to_bit(Z_OBJ_P(entry)); |
111 | 0 | } |
112 | 0 | ZEND_HASH_FOREACH_END(); |
113 | | |
114 | 0 | return events; |
115 | 0 | } |
116 | | |
117 | | static zend_result php_io_poll_events_to_event_enums(uint32_t events, zval *event_enums) |
118 | 0 | { |
119 | 0 | zval enum_case; |
120 | |
|
121 | 0 | array_init(event_enums); |
122 | |
|
123 | 0 | if (events & PHP_POLL_READ) { |
124 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Read)); |
125 | 0 | add_next_index_zval(event_enums, &enum_case); |
126 | 0 | } |
127 | 0 | if (events & PHP_POLL_WRITE) { |
128 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Write)); |
129 | 0 | add_next_index_zval(event_enums, &enum_case); |
130 | 0 | } |
131 | 0 | if (events & PHP_POLL_ERROR) { |
132 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_Error)); |
133 | 0 | add_next_index_zval(event_enums, &enum_case); |
134 | 0 | } |
135 | 0 | if (events & PHP_POLL_HUP) { |
136 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_HangUp)); |
137 | 0 | add_next_index_zval(event_enums, &enum_case); |
138 | 0 | } |
139 | 0 | if (events & PHP_POLL_RDHUP) { |
140 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_ReadHangUp)); |
141 | 0 | add_next_index_zval(event_enums, &enum_case); |
142 | 0 | } |
143 | 0 | if (events & PHP_POLL_ONESHOT) { |
144 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_OneShot)); |
145 | 0 | add_next_index_zval(event_enums, &enum_case); |
146 | 0 | } |
147 | 0 | if (events & PHP_POLL_ET) { |
148 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_by_id(php_io_poll_event_class_entry, ZEND_ENUM_Io_Poll_Event_EdgeTriggered)); |
149 | 0 | add_next_index_zval(event_enums, &enum_case); |
150 | 0 | } |
151 | |
|
152 | 0 | return SUCCESS; |
153 | 0 | } |
154 | | |
155 | | /* Backend enum name to backend type mapping */ |
156 | | static php_poll_backend_type php_io_poll_backend_enum_to_type(zend_object *backend_enum) |
157 | 0 | { |
158 | 0 | return zend_enum_fetch_case_id(backend_enum) - 2; |
159 | 0 | } |
160 | | |
161 | | static const char *php_io_poll_backend_type_to_name(php_poll_backend_type type) |
162 | 0 | { |
163 | 0 | switch (type) { |
164 | 0 | case PHP_POLL_BACKEND_POLL: |
165 | 0 | return "Poll"; |
166 | 0 | case PHP_POLL_BACKEND_EPOLL: |
167 | 0 | return "Epoll"; |
168 | 0 | case PHP_POLL_BACKEND_KQUEUE: |
169 | 0 | return "Kqueue"; |
170 | 0 | case PHP_POLL_BACKEND_EVENTPORT: |
171 | 0 | return "EventPorts"; |
172 | 0 | case PHP_POLL_BACKEND_WSAPOLL: |
173 | 0 | return "WSAPoll"; |
174 | 0 | case PHP_POLL_BACKEND_AUTO: |
175 | 0 | default: |
176 | 0 | return "Auto"; |
177 | 0 | } |
178 | 0 | } |
179 | | |
180 | | /* Stream Poll Handle Implementation */ |
181 | | |
182 | | static php_socket_t php_stream_poll_handle_get_fd(php_poll_handle_object *handle) |
183 | 0 | { |
184 | 0 | php_stream_poll_handle_data *data = handle->handle_data; |
185 | 0 | php_socket_t fd; |
186 | |
|
187 | 0 | if (!data || !data->stream) { |
188 | 0 | return SOCK_ERR; |
189 | 0 | } |
190 | | |
191 | 0 | if (php_stream_cast(data->stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, |
192 | 0 | (void *) &fd, 1) |
193 | 0 | != SUCCESS |
194 | 0 | || fd == -1) { |
195 | 0 | return SOCK_ERR; |
196 | 0 | } |
197 | | |
198 | 0 | return fd; |
199 | 0 | } |
200 | | |
201 | | static int php_stream_poll_handle_is_valid(php_poll_handle_object *handle) |
202 | 0 | { |
203 | 0 | php_stream_poll_handle_data *data = handle->handle_data; |
204 | 0 | return data && data->stream && !php_stream_eof(data->stream); |
205 | 0 | } |
206 | | |
207 | | static void php_stream_poll_handle_cleanup(php_poll_handle_object *handle) |
208 | 5 | { |
209 | 5 | php_stream_poll_handle_data *data = handle->handle_data; |
210 | 5 | if (data) { |
211 | 0 | if (data->res) { |
212 | 0 | zend_list_delete(data->res); |
213 | 0 | } |
214 | 0 | efree(data); |
215 | 0 | handle->handle_data = NULL; |
216 | 0 | } |
217 | 5 | } |
218 | | |
219 | | static php_poll_handle_ops php_stream_poll_handle_ops = { |
220 | | .get_fd = php_stream_poll_handle_get_fd, |
221 | | .is_valid = php_stream_poll_handle_is_valid, |
222 | | .cleanup = php_stream_poll_handle_cleanup |
223 | | }; |
224 | | |
225 | | /* Handle interface internal only */ |
226 | | static int php_stream_poll_handle_implement_interface(zend_class_entry *interface, zend_class_entry *implementor) |
227 | 16 | { |
228 | 16 | if (implementor->type == ZEND_USER_CLASS) { |
229 | 0 | zend_error_noreturn(E_ERROR, "Io\\Poll\\Handle cannot be implemented by user classes"); |
230 | 0 | return FAILURE; |
231 | 0 | } |
232 | | |
233 | 16 | return SUCCESS; |
234 | 16 | } |
235 | | |
236 | | /* Object Creation Functions */ |
237 | | |
238 | | static zend_object *php_stream_poll_handle_create_object(zend_class_entry *ce) |
239 | 5 | { |
240 | 5 | php_poll_handle_object *intern = php_poll_handle_object_create( |
241 | 5 | sizeof(php_poll_handle_object), ce, &php_stream_poll_handle_ops); |
242 | 5 | return &intern->std; |
243 | 5 | } |
244 | | |
245 | | static zend_object *php_io_poll_watcher_create_object(zend_class_entry *ce) |
246 | 5 | { |
247 | 5 | php_io_poll_watcher_object *intern = zend_object_alloc(sizeof(php_io_poll_watcher_object), ce); |
248 | | |
249 | 5 | zend_object_std_init(&intern->std, ce); |
250 | 5 | object_properties_init(&intern->std, ce); |
251 | | |
252 | 5 | intern->handle = NULL; |
253 | 5 | intern->watched_events = 0; |
254 | 5 | intern->triggered_events = 0; |
255 | 5 | intern->active = false; |
256 | 5 | intern->context = NULL; |
257 | 5 | ZVAL_NULL(&intern->data); |
258 | | |
259 | 5 | return &intern->std; |
260 | 5 | } |
261 | | |
262 | | static zend_object *php_io_poll_context_create_object(zend_class_entry *ce) |
263 | 5 | { |
264 | 5 | php_io_poll_context_object *intern = zend_object_alloc(sizeof(php_io_poll_context_object), ce); |
265 | | |
266 | 5 | zend_object_std_init(&intern->std, ce); |
267 | 5 | object_properties_init(&intern->std, ce); |
268 | | |
269 | 5 | intern->ctx = NULL; |
270 | 5 | intern->watchers = NULL; |
271 | | |
272 | 5 | return &intern->std; |
273 | 5 | } |
274 | | |
275 | | /* Object Destruction Functions */ |
276 | | |
277 | | static void php_io_poll_watcher_free_object(zend_object *obj) |
278 | 5 | { |
279 | 5 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(obj); |
280 | | |
281 | 5 | zval_ptr_dtor(&intern->data); |
282 | | |
283 | 5 | if (intern->handle) { |
284 | 0 | OBJ_RELEASE(&intern->handle->std); |
285 | 0 | } |
286 | | |
287 | 5 | zend_object_std_dtor(&intern->std); |
288 | 5 | } |
289 | | |
290 | | static void php_io_poll_context_free_object(zend_object *obj) |
291 | 5 | { |
292 | 5 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(obj); |
293 | | |
294 | 5 | if (intern->watchers) { |
295 | 5 | ZEND_HASH_FOREACH_VAL(intern->watchers, zval *zv) { |
296 | 5 | php_io_poll_watcher_object *watcher = PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(Z_OBJ_P(zv)); |
297 | 5 | watcher->active = false; |
298 | 5 | watcher->context = NULL; |
299 | 5 | } ZEND_HASH_FOREACH_END(); |
300 | 5 | } |
301 | | |
302 | 5 | if (intern->ctx) { |
303 | 5 | php_poll_destroy(intern->ctx); |
304 | 5 | } |
305 | | |
306 | 5 | if (intern->watchers) { |
307 | 5 | zend_hash_destroy(intern->watchers); |
308 | 5 | efree(intern->watchers); |
309 | 5 | } |
310 | | |
311 | 5 | zend_object_std_dtor(&intern->std); |
312 | 5 | } |
313 | | |
314 | | static HashTable *php_io_poll_watcher_get_gc(zend_object *obj, zval **table, int *n) |
315 | 0 | { |
316 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZOBJ(obj); |
317 | 0 | zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); |
318 | |
|
319 | 0 | zend_get_gc_buffer_add_zval(gc_buffer, &intern->data); |
320 | 0 | if (intern->handle) { |
321 | 0 | zend_get_gc_buffer_add_obj(gc_buffer, &intern->handle->std); |
322 | 0 | } |
323 | |
|
324 | 0 | zend_get_gc_buffer_use(gc_buffer, table, n); |
325 | 0 | return NULL; |
326 | 0 | } |
327 | | |
328 | | static HashTable *php_io_poll_context_get_gc(zend_object *obj, zval **table, int *n) |
329 | 0 | { |
330 | 0 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZOBJ(obj); |
331 | 0 | zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); |
332 | |
|
333 | 0 | if (intern->watchers) { |
334 | 0 | ZEND_HASH_FOREACH_VAL(intern->watchers, zval *zv) { |
335 | 0 | zend_get_gc_buffer_add_zval(gc_buffer, zv); |
336 | 0 | } ZEND_HASH_FOREACH_END(); |
337 | 0 | } |
338 | |
|
339 | 0 | zend_get_gc_buffer_use(gc_buffer, table, n); |
340 | 0 | return NULL; |
341 | 0 | } |
342 | | |
343 | | /* Utility functions */ |
344 | | |
345 | | static zend_always_inline zend_ulong php_io_poll_compute_ptr_key(void *ptr) |
346 | 0 | { |
347 | 0 | zend_ulong key = (zend_ulong) (uintptr_t) ptr; |
348 | 0 | return (key >> 3) | (key << ((sizeof(key) * 8) - 3)); |
349 | 0 | } |
350 | | |
351 | | static zend_result php_io_poll_watcher_modify_events( |
352 | | php_io_poll_watcher_object *watcher, uint32_t events) |
353 | 0 | { |
354 | 0 | if (!watcher->active || !watcher->context) { |
355 | 0 | zend_throw_exception( |
356 | 0 | php_io_poll_inactive_watcher_class_entry, "Cannot modify inactive watcher", 0); |
357 | 0 | return FAILURE; |
358 | 0 | } |
359 | | |
360 | 0 | php_socket_t fd = php_poll_handle_get_fd(watcher->handle); |
361 | 0 | if (fd == SOCK_ERR) { |
362 | 0 | zend_throw_exception( |
363 | 0 | php_io_poll_invalid_handle_class_entry, "Invalid handle for polling", 0); |
364 | 0 | return FAILURE; |
365 | 0 | } |
366 | | |
367 | | /* Modify in poll context */ |
368 | 0 | php_poll_ctx *poll_ctx = watcher->context->ctx; |
369 | 0 | if (php_poll_modify(poll_ctx, (int) fd, events, watcher) != SUCCESS) { |
370 | 0 | php_poll_error err = php_poll_get_error(poll_ctx); |
371 | 0 | php_io_poll_throw_failed_operation(php_io_poll_failed_watcher_mod_class_entry, |
372 | 0 | "Failed to modify watcher in polling system", err); |
373 | 0 | return FAILURE; |
374 | 0 | } |
375 | | |
376 | | /* Update watcher state */ |
377 | 0 | watcher->watched_events = events; |
378 | |
|
379 | 0 | return SUCCESS; |
380 | 0 | } |
381 | | |
382 | | static zend_result php_io_poll_watcher_modify_data(php_io_poll_watcher_object *watcher, zval *data) |
383 | 0 | { |
384 | 0 | if (!watcher->active) { |
385 | 0 | zend_throw_exception( |
386 | 0 | php_io_poll_inactive_watcher_class_entry, "Cannot modify inactive watcher", 0); |
387 | 0 | return FAILURE; |
388 | 0 | } |
389 | | |
390 | | /* Update user data */ |
391 | 0 | zval_ptr_dtor(&watcher->data); |
392 | 0 | ZVAL_COPY(&watcher->data, data); |
393 | |
|
394 | 0 | return SUCCESS; |
395 | 0 | } |
396 | | |
397 | | /* PHP Method Implementations */ |
398 | | |
399 | | PHP_METHOD(Io_Poll_Backend, getAvailableBackends) |
400 | 0 | { |
401 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
402 | | |
403 | 0 | array_init(return_value); |
404 | | |
405 | | /* Check each backend type for availability */ |
406 | 0 | php_poll_backend_type backends[] = {PHP_POLL_BACKEND_POLL, PHP_POLL_BACKEND_EPOLL, |
407 | 0 | PHP_POLL_BACKEND_KQUEUE, PHP_POLL_BACKEND_EVENTPORT, PHP_POLL_BACKEND_WSAPOLL}; |
408 | |
|
409 | 0 | for (size_t i = 0; i < sizeof(backends) / sizeof(backends[0]); i++) { |
410 | 0 | if (php_poll_is_backend_available(backends[i])) { |
411 | 0 | const char *name = php_io_poll_backend_type_to_name(backends[i]); |
412 | 0 | zval enum_case; |
413 | 0 | ZVAL_OBJ_COPY(&enum_case, zend_enum_get_case_cstr(php_io_poll_backend_class_entry, name)); |
414 | 0 | add_next_index_zval(return_value, &enum_case); |
415 | 0 | } |
416 | 0 | } |
417 | 0 | } |
418 | | |
419 | | PHP_METHOD(Io_Poll_Backend, isAvailable) |
420 | 0 | { |
421 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
422 | | |
423 | 0 | zend_object *enum_obj = Z_OBJ_P(ZEND_THIS); |
424 | 0 | php_poll_backend_type type = php_io_poll_backend_enum_to_type(enum_obj); |
425 | |
|
426 | 0 | RETURN_BOOL(php_poll_is_backend_available(type)); |
427 | 0 | } |
428 | | |
429 | | PHP_METHOD(Io_Poll_Backend, supportsEdgeTriggering) |
430 | 0 | { |
431 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
432 | | |
433 | 0 | zend_object *enum_obj = Z_OBJ_P(ZEND_THIS); |
434 | 0 | php_poll_backend_type type = php_io_poll_backend_enum_to_type(enum_obj); |
435 | |
|
436 | 0 | RETURN_BOOL(php_poll_backend_supports_edge_triggering(type)); |
437 | 0 | } |
438 | | |
439 | | PHP_METHOD(StreamPollHandle, __construct) |
440 | 5 | { |
441 | 5 | php_stream *stream; |
442 | | |
443 | 10 | ZEND_PARSE_PARAMETERS_START(1, 1) |
444 | 10 | PHP_Z_PARAM_STREAM(stream) |
445 | 5 | ZEND_PARSE_PARAMETERS_END(); |
446 | | |
447 | 0 | php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZV(getThis()); |
448 | |
|
449 | 0 | if (intern->handle_data) { |
450 | 0 | zend_throw_error(NULL, "StreamPollHandle object is already constructed"); |
451 | 0 | RETURN_THROWS(); |
452 | 0 | } |
453 | | |
454 | | /* Set up stream-specific data */ |
455 | 0 | php_stream_poll_handle_data *data = emalloc(sizeof(php_stream_poll_handle_data)); |
456 | 0 | data->stream = stream; |
457 | 0 | data->res = stream->res; |
458 | 0 | intern->handle_data = data; |
459 | | |
460 | | /* Add reference to stream */ |
461 | 0 | GC_ADDREF(data->res); |
462 | 0 | } |
463 | | |
464 | | PHP_METHOD(StreamPollHandle, getStream) |
465 | 0 | { |
466 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
467 | | |
468 | 0 | php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZV(getThis()); |
469 | 0 | php_stream_poll_handle_data *data = intern->handle_data; |
470 | |
|
471 | 0 | if (!data || !data->stream) { |
472 | 0 | RETURN_NULL(); |
473 | 0 | } |
474 | | |
475 | 0 | GC_ADDREF(data->stream->res); |
476 | 0 | php_stream_to_zval(data->stream, return_value); |
477 | 0 | } |
478 | | |
479 | | PHP_METHOD(StreamPollHandle, isValid) |
480 | 0 | { |
481 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
482 | | |
483 | 0 | php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZV(getThis()); |
484 | 0 | RETURN_BOOL(intern->ops->is_valid(intern)); |
485 | 0 | } |
486 | | |
487 | | PHP_METHOD(StreamPollHandle, getFileDescriptor) |
488 | 0 | { |
489 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
490 | | |
491 | 0 | php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZV(getThis()); |
492 | 0 | php_socket_t fd = php_poll_handle_get_fd(intern); |
493 | |
|
494 | 0 | if (fd == SOCK_ERR) { |
495 | 0 | RETURN_LONG(0); |
496 | 0 | } |
497 | | |
498 | 0 | RETURN_LONG((zend_long) fd); |
499 | 0 | } |
500 | | |
501 | | PHP_METHOD(Io_Poll_Watcher, __construct) |
502 | 0 | { |
503 | 0 | zend_throw_error(NULL, "Cannot directly construct Watcher, use Context::add"); |
504 | 0 | } |
505 | | |
506 | | PHP_METHOD(Io_Poll_Watcher, getHandle) |
507 | 0 | { |
508 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
509 | | |
510 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
511 | 0 | if (!intern->handle) { |
512 | 0 | RETURN_NULL(); |
513 | 0 | } |
514 | | |
515 | 0 | RETURN_OBJ_COPY(&intern->handle->std); |
516 | 0 | } |
517 | | |
518 | | PHP_METHOD(Io_Poll_Watcher, getWatchedEvents) |
519 | 0 | { |
520 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
521 | | |
522 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
523 | 0 | php_io_poll_events_to_event_enums(intern->watched_events, return_value); |
524 | 0 | } |
525 | | |
526 | | PHP_METHOD(Io_Poll_Watcher, getTriggeredEvents) |
527 | 0 | { |
528 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
529 | | |
530 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
531 | 0 | php_io_poll_events_to_event_enums(intern->triggered_events, return_value); |
532 | 0 | } |
533 | | |
534 | | PHP_METHOD(Io_Poll_Watcher, getData) |
535 | 0 | { |
536 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
537 | | |
538 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
539 | 0 | ZVAL_COPY(return_value, &intern->data); |
540 | 0 | } |
541 | | |
542 | | PHP_METHOD(Io_Poll_Watcher, hasTriggered) |
543 | 0 | { |
544 | 0 | zval *event_enum; |
545 | |
|
546 | 0 | ZEND_PARSE_PARAMETERS_START(1, 1) |
547 | 0 | Z_PARAM_OBJECT_OF_CLASS(event_enum, php_io_poll_event_class_entry) |
548 | 0 | ZEND_PARSE_PARAMETERS_END(); |
549 | | |
550 | 0 | uint32_t event_bit = php_io_poll_event_enum_to_bit(Z_OBJ_P(event_enum)); |
551 | |
|
552 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
553 | 0 | RETURN_BOOL((intern->triggered_events & event_bit) != 0); |
554 | 0 | } |
555 | | |
556 | | PHP_METHOD(Io_Poll_Watcher, isActive) |
557 | 0 | { |
558 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
559 | | |
560 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
561 | 0 | RETURN_BOOL(intern->active); |
562 | 0 | } |
563 | | |
564 | | PHP_METHOD(Io_Poll_Watcher, modify) |
565 | 0 | { |
566 | 0 | zval *event_enums; |
567 | 0 | zval *data = NULL; |
568 | |
|
569 | 0 | ZEND_PARSE_PARAMETERS_START(1, 2) |
570 | 0 | Z_PARAM_ARRAY(event_enums) |
571 | 0 | Z_PARAM_OPTIONAL |
572 | 0 | Z_PARAM_ZVAL(data) |
573 | 0 | ZEND_PARSE_PARAMETERS_END(); |
574 | | |
575 | 0 | uint32_t events = php_io_poll_event_enums_to_events(event_enums); |
576 | 0 | if (!events) { |
577 | 0 | zend_argument_type_error(1, "must be array of Event enums"); |
578 | 0 | RETURN_THROWS(); |
579 | 0 | } |
580 | | |
581 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
582 | | |
583 | | /* Modify events first */ |
584 | 0 | if (php_io_poll_watcher_modify_events(intern, events) != SUCCESS) { |
585 | 0 | RETURN_THROWS(); |
586 | 0 | } |
587 | | |
588 | | /* Then modify data if provided */ |
589 | 0 | if (data) { |
590 | 0 | if (php_io_poll_watcher_modify_data(intern, data) != SUCCESS) { |
591 | 0 | RETURN_THROWS(); |
592 | 0 | } |
593 | 0 | } |
594 | 0 | } |
595 | | |
596 | | PHP_METHOD(Io_Poll_Watcher, modifyEvents) |
597 | 0 | { |
598 | 0 | zval *event_enums; |
599 | |
|
600 | 0 | ZEND_PARSE_PARAMETERS_START(1, 1) |
601 | 0 | Z_PARAM_ARRAY(event_enums) |
602 | 0 | ZEND_PARSE_PARAMETERS_END(); |
603 | | |
604 | 0 | uint32_t events = php_io_poll_event_enums_to_events(event_enums); |
605 | 0 | if (!events) { |
606 | 0 | zend_argument_type_error(1, "must be array of Event enums"); |
607 | 0 | RETURN_THROWS(); |
608 | 0 | } |
609 | | |
610 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
611 | |
|
612 | 0 | if (php_io_poll_watcher_modify_events(intern, events) != SUCCESS) { |
613 | 0 | RETURN_THROWS(); |
614 | 0 | } |
615 | 0 | } |
616 | | |
617 | | PHP_METHOD(Io_Poll_Watcher, modifyData) |
618 | 0 | { |
619 | 0 | zval *data; |
620 | |
|
621 | 0 | ZEND_PARSE_PARAMETERS_START(1, 1) |
622 | 0 | Z_PARAM_ZVAL(data) |
623 | 0 | ZEND_PARSE_PARAMETERS_END(); |
624 | | |
625 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
626 | |
|
627 | 0 | if (php_io_poll_watcher_modify_data(intern, data) != SUCCESS) { |
628 | 0 | RETURN_THROWS(); |
629 | 0 | } |
630 | 0 | } |
631 | | |
632 | | PHP_METHOD(Io_Poll_Watcher, remove) |
633 | 0 | { |
634 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
635 | | |
636 | 0 | php_io_poll_watcher_object *intern = PHP_POLL_WATCHER_OBJ_FROM_ZV(getThis()); |
637 | |
|
638 | 0 | if (!intern->active || !intern->context) { |
639 | 0 | zend_throw_exception( |
640 | 0 | php_io_poll_inactive_watcher_class_entry, "Cannot remove inactive watcher", 0); |
641 | 0 | RETURN_THROWS(); |
642 | 0 | } |
643 | | |
644 | 0 | php_io_poll_context_object *context = intern->context; |
645 | 0 | php_poll_ctx *poll_ctx = context->ctx; |
646 | 0 | HashTable *watchers = context->watchers; |
647 | 0 | zend_ulong hash_key = php_io_poll_compute_ptr_key(intern->handle); |
648 | 0 | php_socket_t fd = php_poll_handle_get_fd(intern->handle); |
649 | 0 | if (fd != SOCK_ERR) { |
650 | 0 | php_poll_remove(poll_ctx, (int) fd); |
651 | 0 | } |
652 | |
|
653 | 0 | intern->active = false; |
654 | 0 | intern->context = NULL; |
655 | |
|
656 | 0 | if (watchers) { |
657 | 0 | zend_hash_index_del(watchers, hash_key); |
658 | 0 | } |
659 | 0 | } |
660 | | |
661 | | PHP_METHOD(Io_Poll_Context, __construct) |
662 | 5 | { |
663 | 5 | zval *backend_obj = NULL; |
664 | | |
665 | 15 | ZEND_PARSE_PARAMETERS_START(0, 1) |
666 | 15 | Z_PARAM_OPTIONAL |
667 | 15 | Z_PARAM_OBJECT_OF_CLASS(backend_obj, php_io_poll_backend_class_entry) |
668 | 5 | ZEND_PARSE_PARAMETERS_END(); |
669 | | |
670 | 5 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZV(getThis()); |
671 | | |
672 | 5 | if (intern->ctx) { |
673 | 0 | zend_throw_error(NULL, "Io\\Poll\\Context object is already constructed"); |
674 | 0 | RETURN_THROWS(); |
675 | 0 | } |
676 | | |
677 | 5 | php_poll_backend_type backend_type = PHP_POLL_BACKEND_AUTO; |
678 | 5 | if (backend_obj != NULL) { |
679 | 0 | backend_type = php_io_poll_backend_enum_to_type(Z_OBJ_P(backend_obj)); |
680 | 0 | } |
681 | | |
682 | 5 | intern->ctx = php_poll_create(backend_type, 0); |
683 | | |
684 | 5 | if (!intern->ctx) { |
685 | 0 | zend_throw_exception_ex( |
686 | 0 | php_io_poll_failed_backend_unavailable_class_entry, 0, "Backend %s not available", |
687 | 0 | php_io_poll_backend_type_to_name(backend_type)); |
688 | 0 | RETURN_THROWS(); |
689 | 0 | } |
690 | | |
691 | 5 | if (php_poll_init(intern->ctx) != SUCCESS) { |
692 | 0 | php_poll_error err = php_poll_get_error(intern->ctx); |
693 | 0 | php_poll_destroy(intern->ctx); |
694 | 0 | intern->ctx = NULL; |
695 | 0 | php_io_poll_throw_failed_operation(php_io_poll_failed_context_init_class_entry, |
696 | 0 | "Failed to initialize polling context", err); |
697 | 0 | RETURN_THROWS(); |
698 | 0 | } |
699 | | |
700 | 5 | intern->watchers = emalloc(sizeof(HashTable)); |
701 | 5 | zend_hash_init(intern->watchers, 8, NULL, ZVAL_PTR_DTOR, 0); |
702 | 5 | } |
703 | | |
704 | | PHP_METHOD(Io_Poll_Context, add) |
705 | 0 | { |
706 | 0 | zval *handle_obj, *event_enums; |
707 | 0 | uint32_t events; |
708 | 0 | zval *data = NULL; |
709 | |
|
710 | 0 | ZEND_PARSE_PARAMETERS_START(2, 3) |
711 | 0 | Z_PARAM_OBJECT_OF_CLASS(handle_obj, php_io_poll_handle_class_entry) |
712 | 0 | Z_PARAM_ARRAY(event_enums) |
713 | 0 | Z_PARAM_OPTIONAL |
714 | 0 | Z_PARAM_ZVAL(data) |
715 | 0 | ZEND_PARSE_PARAMETERS_END(); |
716 | | |
717 | 0 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZV(getThis()); |
718 | 0 | php_poll_handle_object *handle = PHP_POLL_HANDLE_OBJ_FROM_ZV(handle_obj); |
719 | | |
720 | | /* Get file descriptor */ |
721 | 0 | php_socket_t fd = php_poll_handle_get_fd(handle); |
722 | 0 | if (fd == SOCK_ERR) { |
723 | 0 | zend_throw_exception( |
724 | 0 | php_io_poll_invalid_handle_class_entry, "Invalid handle for polling", 0); |
725 | 0 | RETURN_THROWS(); |
726 | 0 | } |
727 | | |
728 | | /* Create watcher object */ |
729 | 0 | object_init_ex(return_value, php_io_poll_watcher_class_entry); |
730 | 0 | php_io_poll_watcher_object *watcher = PHP_POLL_WATCHER_OBJ_FROM_ZV(return_value); |
731 | |
|
732 | 0 | events = php_io_poll_event_enums_to_events(event_enums); |
733 | 0 | if (!events) { |
734 | 0 | zend_argument_type_error(2, "must be array of Event enums"); |
735 | 0 | RETURN_THROWS(); |
736 | 0 | } |
737 | | |
738 | 0 | watcher->handle = handle; |
739 | 0 | watcher->watched_events = events; |
740 | 0 | watcher->triggered_events = 0; |
741 | |
|
742 | 0 | GC_ADDREF(&handle->std); |
743 | |
|
744 | 0 | if (data) { |
745 | 0 | ZVAL_COPY(&watcher->data, data); |
746 | 0 | } else { |
747 | 0 | ZVAL_NULL(&watcher->data); |
748 | 0 | } |
749 | | |
750 | | /* Add to poll context */ |
751 | 0 | if (php_poll_add(intern->ctx, (int) fd, events, watcher) != SUCCESS) { |
752 | 0 | php_poll_error err = php_poll_get_error(intern->ctx); |
753 | 0 | if (err == PHP_POLL_ERR_EXISTS) { |
754 | 0 | zend_throw_exception( |
755 | 0 | php_io_poll_handle_already_watched_class_entry, "Handle already added", 0); |
756 | 0 | } else { |
757 | 0 | php_io_poll_throw_failed_operation( |
758 | 0 | php_io_poll_failed_handle_add_class_entry, "Failed to add handle", err); |
759 | 0 | } |
760 | 0 | RETURN_THROWS(); |
761 | 0 | } |
762 | | |
763 | | /* Store in our watchers map using shifted pointer as key */ |
764 | 0 | zval watcher_zv; |
765 | 0 | ZVAL_OBJ(&watcher_zv, &watcher->std); |
766 | 0 | GC_ADDREF(&watcher->std); |
767 | |
|
768 | 0 | zend_ulong hash_key = php_io_poll_compute_ptr_key(handle); |
769 | 0 | zend_hash_index_add_new(intern->watchers, hash_key, &watcher_zv); |
770 | |
|
771 | 0 | watcher->active = true; |
772 | 0 | watcher->context = intern; |
773 | 0 | } |
774 | | |
775 | | PHP_METHOD(Io_Poll_Context, wait) |
776 | 0 | { |
777 | 0 | zend_long timeout_seconds = -1; |
778 | 0 | bool timeout_seconds_is_null = true; |
779 | 0 | zend_long timeout_microseconds = 0; |
780 | 0 | zend_long max_events = 0; |
781 | 0 | bool max_events_is_null = true; |
782 | |
|
783 | 0 | ZEND_PARSE_PARAMETERS_START(0, 3) |
784 | 0 | Z_PARAM_OPTIONAL |
785 | 0 | Z_PARAM_LONG_OR_NULL(timeout_seconds, timeout_seconds_is_null) |
786 | 0 | Z_PARAM_LONG(timeout_microseconds) |
787 | 0 | Z_PARAM_LONG_OR_NULL(max_events, max_events_is_null) |
788 | 0 | ZEND_PARSE_PARAMETERS_END(); |
789 | | |
790 | 0 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZV(getThis()); |
791 | | |
792 | | /* Build timespec from seconds + microseconds, or NULL for indefinite */ |
793 | 0 | struct timespec ts; |
794 | 0 | const struct timespec *timeout = NULL; |
795 | 0 | if (timeout_seconds >= 0) { |
796 | 0 | if (timeout_microseconds < 0) { |
797 | 0 | zend_argument_value_error(2, "must be greater than or equal to 0"); |
798 | 0 | RETURN_THROWS(); |
799 | 0 | } |
800 | | |
801 | | /* Allow microseconds >= 1000000, carry overflow into seconds |
802 | | * (same behavior as stream_select) */ |
803 | 0 | ts.tv_sec = (time_t) (timeout_seconds + (timeout_microseconds / 1000000)); |
804 | 0 | ts.tv_nsec = (long) ((timeout_microseconds % 1000000) * 1000); |
805 | 0 | timeout = &ts; |
806 | 0 | } else if (!timeout_seconds_is_null) { |
807 | 0 | zend_argument_value_error(1, "must be greater than or equal to 0"); |
808 | 0 | RETURN_THROWS(); |
809 | 0 | } |
810 | | |
811 | 0 | if (max_events_is_null) { |
812 | 0 | max_events = php_poll_get_suitable_max_events(intern->ctx); |
813 | 0 | if (max_events <= 0) { |
814 | 0 | max_events = 64; |
815 | 0 | } |
816 | 0 | } else if (max_events <= 0) { |
817 | 0 | zend_argument_value_error(3, "must be greater than 0"); |
818 | 0 | RETURN_THROWS(); |
819 | 0 | } |
820 | | |
821 | 0 | php_poll_event *events = safe_emalloc(max_events, sizeof(*events), 0); |
822 | 0 | int num_events = php_poll_wait(intern->ctx, events, (int) max_events, timeout); |
823 | |
|
824 | 0 | if (num_events < 0) { |
825 | 0 | php_poll_error err = php_poll_get_error(intern->ctx); |
826 | 0 | efree(events); |
827 | 0 | php_io_poll_throw_failed_operation( |
828 | 0 | php_io_poll_failed_wait_class_entry, "Poll wait failed", err); |
829 | 0 | RETURN_THROWS(); |
830 | 0 | } |
831 | | |
832 | 0 | array_init(return_value); |
833 | |
|
834 | 0 | for (int i = 0; i < num_events; i++) { |
835 | 0 | php_io_poll_watcher_object *watcher = (php_io_poll_watcher_object *) events[i].data; |
836 | 0 | if (watcher) { |
837 | 0 | watcher->triggered_events = events[i].revents; |
838 | |
|
839 | 0 | zval watcher_zv; |
840 | 0 | ZVAL_OBJ(&watcher_zv, &watcher->std); |
841 | 0 | GC_ADDREF(&watcher->std); |
842 | |
|
843 | 0 | add_next_index_zval(return_value, &watcher_zv); |
844 | 0 | } |
845 | 0 | } |
846 | |
|
847 | 0 | efree(events); |
848 | 0 | } |
849 | | |
850 | | PHP_METHOD(Io_Poll_Context, getBackend) |
851 | 0 | { |
852 | 0 | ZEND_PARSE_PARAMETERS_NONE(); |
853 | | |
854 | 0 | php_io_poll_context_object *intern = PHP_POLL_CONTEXT_OBJ_FROM_ZV(getThis()); |
855 | 0 | php_poll_backend_type backend_type = php_poll_get_backend_type(intern->ctx); |
856 | 0 | const char *backend_name = php_io_poll_backend_type_to_name(backend_type); |
857 | |
|
858 | 0 | RETURN_OBJ_COPY(zend_enum_get_case_cstr(php_io_poll_backend_class_entry, backend_name)); |
859 | 0 | } |
860 | | |
861 | | /* Initialize the stream poll classes - add to PHP_MINIT_FUNCTION */ |
862 | | PHP_MINIT_FUNCTION(poll) |
863 | 16 | { |
864 | | /* Register backend enum */ |
865 | 16 | php_io_poll_backend_class_entry = register_class_Io_Poll_Backend(); |
866 | | |
867 | | /* Register event enum */ |
868 | 16 | php_io_poll_event_class_entry = register_class_Io_Poll_Event(); |
869 | | |
870 | | /* Register Handle interface */ |
871 | 16 | php_io_poll_handle_class_entry = register_class_Io_Poll_Handle(); |
872 | 16 | php_io_poll_handle_class_entry->interface_gets_implemented = php_stream_poll_handle_implement_interface; |
873 | | |
874 | | /* Register StreamPollHandle class */ |
875 | 16 | php_stream_poll_handle_class_entry |
876 | 16 | = register_class_StreamPollHandle(php_io_poll_handle_class_entry); |
877 | 16 | php_stream_poll_handle_class_entry->create_object = php_stream_poll_handle_create_object; |
878 | | |
879 | 16 | memcpy(&php_io_poll_handle_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); |
880 | 16 | php_io_poll_handle_object_handlers.offset = offsetof(php_poll_handle_object, std); |
881 | 16 | php_io_poll_handle_object_handlers.free_obj = php_poll_handle_object_free; |
882 | 16 | php_io_poll_handle_object_handlers.clone_obj = NULL; |
883 | 16 | php_stream_poll_handle_class_entry->default_object_handlers = &php_io_poll_handle_object_handlers; |
884 | | |
885 | | /* Register Watcher class */ |
886 | 16 | php_io_poll_watcher_class_entry = register_class_Io_Poll_Watcher(); |
887 | 16 | php_io_poll_watcher_class_entry->create_object = php_io_poll_watcher_create_object; |
888 | | |
889 | 16 | memcpy(&php_io_poll_watcher_object_handlers, &std_object_handlers, |
890 | 16 | sizeof(zend_object_handlers)); |
891 | 16 | php_io_poll_watcher_object_handlers.offset = offsetof(php_io_poll_watcher_object, std); |
892 | 16 | php_io_poll_watcher_object_handlers.free_obj = php_io_poll_watcher_free_object; |
893 | 16 | php_io_poll_watcher_object_handlers.get_gc = php_io_poll_watcher_get_gc; |
894 | 16 | php_io_poll_watcher_object_handlers.clone_obj = NULL; |
895 | 16 | php_io_poll_watcher_class_entry->default_object_handlers = &php_io_poll_watcher_object_handlers; |
896 | | |
897 | | /* Register Context class */ |
898 | 16 | php_io_poll_context_class_entry = register_class_Io_Poll_Context(); |
899 | 16 | php_io_poll_context_class_entry->create_object = php_io_poll_context_create_object; |
900 | | |
901 | 16 | memcpy(&php_io_poll_context_object_handlers, &std_object_handlers, |
902 | 16 | sizeof(zend_object_handlers)); |
903 | 16 | php_io_poll_context_object_handlers.offset = offsetof(php_io_poll_context_object, std); |
904 | 16 | php_io_poll_context_object_handlers.free_obj = php_io_poll_context_free_object; |
905 | 16 | php_io_poll_context_object_handlers.get_gc = php_io_poll_context_get_gc; |
906 | 16 | php_io_poll_context_object_handlers.clone_obj = NULL; |
907 | 16 | php_io_poll_context_class_entry->default_object_handlers = &php_io_poll_context_object_handlers; |
908 | | |
909 | | /* Register exception hierarchy */ |
910 | 16 | php_io_exception_class_entry = register_class_Io_IoException(zend_ce_exception); |
911 | | |
912 | 16 | php_io_poll_exception_class_entry |
913 | 16 | = register_class_Io_Poll_PollException(php_io_exception_class_entry); |
914 | | |
915 | 16 | php_io_poll_failed_operation_class_entry = register_class_Io_Poll_FailedPollOperationException( |
916 | 16 | php_io_poll_exception_class_entry); |
917 | | |
918 | 16 | php_io_poll_failed_context_init_class_entry |
919 | 16 | = register_class_Io_Poll_FailedContextInitializationException( |
920 | 16 | php_io_poll_failed_operation_class_entry); |
921 | | |
922 | 16 | php_io_poll_failed_handle_add_class_entry = register_class_Io_Poll_FailedHandleAddException( |
923 | 16 | php_io_poll_failed_operation_class_entry); |
924 | | |
925 | 16 | php_io_poll_failed_watcher_mod_class_entry |
926 | 16 | = register_class_Io_Poll_FailedWatcherModificationException( |
927 | 16 | php_io_poll_failed_operation_class_entry); |
928 | | |
929 | 16 | php_io_poll_failed_wait_class_entry = register_class_Io_Poll_FailedPollWaitException( |
930 | 16 | php_io_poll_failed_operation_class_entry); |
931 | | |
932 | 16 | php_io_poll_failed_backend_unavailable_class_entry = register_class_Io_Poll_BackendUnavailableException( |
933 | 16 | php_io_poll_exception_class_entry); |
934 | | |
935 | 16 | php_io_poll_inactive_watcher_class_entry = register_class_Io_Poll_InactiveWatcherException( |
936 | 16 | php_io_poll_exception_class_entry); |
937 | | |
938 | 16 | php_io_poll_handle_already_watched_class_entry |
939 | 16 | = register_class_Io_Poll_HandleAlreadyWatchedException( |
940 | 16 | php_io_poll_exception_class_entry); |
941 | | |
942 | 16 | php_io_poll_invalid_handle_class_entry |
943 | 16 | = register_class_Io_Poll_InvalidHandleException(php_io_poll_exception_class_entry); |
944 | | |
945 | | /* Initialize polling backends */ |
946 | 16 | php_poll_register_backends(); |
947 | | |
948 | 16 | return SUCCESS; |
949 | 16 | } |