Coverage Report

Created: 2026-07-25 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/php-src/main/poll/poll_handle.c
Line
Count
Source
1
/*
2
   +----------------------------------------------------------------------+
3
   | Copyright © The PHP Group and Contributors.                          |
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
   | Authors: Jakub Zelenka <bukka@php.net>                               |
12
   +----------------------------------------------------------------------+
13
*/
14
15
#include "php_poll.h"
16
#include "zend_exceptions.h"
17
18
/* Default get_fd implementation - calls PHP method */
19
static php_socket_t php_poll_handle_default_get_fd(php_poll_handle_object *handle)
20
0
{
21
0
  zval retval;
22
23
  /* Grab getFileDescriptor() method pointer which is stored in lowercase in the function table */
24
0
  zend_function *method = zend_hash_str_find_ptr_lc(&handle->std.ce->function_table, ZEND_STRL("getfiledescriptor"));
25
0
  ZEND_ASSERT(method && "no default method???");
26
27
  /* Call getFileDescriptor() method */
28
0
  zend_call_known_function(method, &handle->std, handle->std.ce, &retval, 0, NULL, NULL);
29
30
  /* No need to deref the return value as the class is final and thus the method cannot be changed to return by-ref */
31
0
  if (EXPECTED(Z_TYPE(retval) == IS_LONG)) {
32
0
    php_socket_t fd = Z_LVAL(retval) < 0 ? SOCK_ERR : (php_socket_t) Z_LVAL(retval);
33
    /* No need to clean the retval as we know it is an integer, and thus it's just on the stack */
34
0
    return fd;
35
0
  }
36
37
0
  zval_ptr_dtor(&retval);
38
0
  return SOCK_ERR; /* Invalid socket */
39
0
}
40
41
/* Default is_valid implementation - assume valid if we can get FD */
42
static int php_poll_handle_default_is_valid(php_poll_handle_object *handle)
43
0
{
44
0
  return php_poll_handle_get_fd(handle) != SOCK_ERR;
45
0
}
46
47
/* Default cleanup */
48
static void php_poll_handle_default_cleanup(php_poll_handle_object *handle)
49
0
{
50
  /* Base implementation has no cleanup */
51
0
}
52
53
/* Default operations that call PHP userspace methods */
54
php_poll_handle_ops php_poll_handle_default_ops = { .get_fd = php_poll_handle_default_get_fd,
55
  .is_valid = php_poll_handle_default_is_valid,
56
  .cleanup = php_poll_handle_default_cleanup };
57
58
/* Allocate a new poll handle object */
59
PHPAPI php_poll_handle_object *php_poll_handle_object_create(
60
    size_t obj_size, zend_class_entry *ce, php_poll_handle_ops *ops)
61
5
{
62
5
  php_poll_handle_object *intern = zend_object_alloc(obj_size, ce);
63
64
5
  zend_object_std_init(&intern->std, ce);
65
5
  object_properties_init(&intern->std, ce);
66
67
5
  intern->ops = ops ? ops : &php_poll_handle_default_ops;
68
5
  intern->handle_data = NULL;
69
70
5
  return intern;
71
5
}
72
73
/* Free poll handle object */
74
PHPAPI void php_poll_handle_object_free(zend_object *obj)
75
5
{
76
5
  php_poll_handle_object *intern = PHP_POLL_HANDLE_OBJ_FROM_ZOBJ(obj);
77
78
5
  if (intern->ops && intern->ops->cleanup) {
79
5
    intern->ops->cleanup(intern);
80
5
  }
81
82
5
  zend_object_std_dtor(&intern->std);
83
5
}
84
85
/* Get file descriptor from handle using ops */
86
PHPAPI php_socket_t php_poll_handle_get_fd(php_poll_handle_object *handle)
87
0
{
88
0
  if (!handle || !handle->ops || !handle->ops->get_fd) {
89
0
    return SOCK_ERR;
90
0
  }
91
92
0
  return handle->ops->get_fd(handle);
93
0
}