Coverage Report

Created: 2026-03-07 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/c-ares/src/lib/event/ares_event_select.c
Line
Count
Source
1
/* MIT License
2
 *
3
 * Copyright (c) 2024 Brad House
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
6
 * of this software and associated documentation files (the "Software"), to deal
7
 * in the Software without restriction, including without limitation the rights
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
 * copies of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 * SPDX-License-Identifier: MIT
25
 */
26
27
/* Some systems might default to something low like 256 (NetBSD), lets define
28
 * this to assist.  Really, no one should be using select, but lets be safe
29
 * anyhow */
30
#define FD_SETSIZE 4096
31
32
#include "ares_private.h"
33
#include "ares_event.h"
34
35
/* All systems have select(), but not all have a way to wake, so we require
36
 * pipe() to wake the select() */
37
#if defined(HAVE_PIPE) && defined(CARES_THREADS)
38
39
#ifdef HAVE_SYS_SELECT_H
40
#  include <sys/select.h>
41
#endif
42
43
static ares_bool_t ares_evsys_select_init(ares_event_thread_t *e)
44
0
{
45
0
  e->ev_signal = ares_pipeevent_create(e);
46
0
  if (e->ev_signal == NULL) {
47
0
    return ARES_FALSE; /* LCOV_EXCL_LINE: UntestablePath */
48
0
  }
49
0
  return ARES_TRUE;
50
0
}
51
52
static void ares_evsys_select_destroy(ares_event_thread_t *e)
53
0
{
54
0
  (void)e;
55
0
}
56
57
static ares_bool_t ares_evsys_select_event_add(ares_event_t *event)
58
0
{
59
0
  (void)event;
60
0
  return ARES_TRUE;
61
0
}
62
63
static void ares_evsys_select_event_del(ares_event_t *event)
64
0
{
65
0
  (void)event;
66
0
}
67
68
static void ares_evsys_select_event_mod(ares_event_t      *event,
69
                                        ares_event_flags_t new_flags)
70
0
{
71
0
  (void)event;
72
0
  (void)new_flags;
73
0
}
74
75
static size_t ares_evsys_select_wait(ares_event_thread_t *e,
76
                                     unsigned long        timeout_ms)
77
0
{
78
0
  size_t          num_fds = 0;
79
0
  ares_socket_t  *fdlist  = ares_htable_asvp_keys(e->ev_sock_handles, &num_fds);
80
0
  int             rv;
81
0
  size_t          cnt = 0;
82
0
  size_t          i;
83
0
  fd_set          read_fds;
84
0
  fd_set          write_fds;
85
0
  fd_set          except_fds;
86
0
  int             nfds = 0;
87
0
  struct timeval  tv;
88
0
  struct timeval *tout = NULL;
89
90
0
  FD_ZERO(&read_fds);
91
0
  FD_ZERO(&write_fds);
92
0
  FD_ZERO(&except_fds);
93
94
0
  for (i = 0; i < num_fds; i++) {
95
0
    const ares_event_t *ev =
96
0
      ares_htable_asvp_get_direct(e->ev_sock_handles, fdlist[i]);
97
0
    if (ev->flags & ARES_EVENT_FLAG_READ) {
98
0
      FD_SET(ev->fd, &read_fds);
99
0
    }
100
0
    if (ev->flags & ARES_EVENT_FLAG_WRITE) {
101
0
      FD_SET(ev->fd, &write_fds);
102
0
    }
103
0
    FD_SET(ev->fd, &except_fds);
104
0
    if (ev->fd + 1 > nfds) {
105
0
      nfds = ev->fd + 1;
106
0
    }
107
0
  }
108
109
0
  if (timeout_ms) {
110
0
    tv.tv_sec  = (int)(timeout_ms / 1000);
111
0
    tv.tv_usec = (int)((timeout_ms % 1000) * 1000);
112
0
    tout       = &tv;
113
0
  }
114
115
0
  rv = select(nfds, &read_fds, &write_fds, &except_fds, tout);
116
0
  if (rv > 0) {
117
0
    for (i = 0; i < num_fds; i++) {
118
0
      ares_event_t      *ev;
119
0
      ares_event_flags_t flags = 0;
120
121
0
      ev = ares_htable_asvp_get_direct(e->ev_sock_handles, fdlist[i]);
122
0
      if (ev == NULL || ev->cb == NULL) {
123
0
        continue; /* LCOV_EXCL_LINE: DefensiveCoding */
124
0
      }
125
126
0
      if (FD_ISSET(fdlist[i], &read_fds) || FD_ISSET(fdlist[i], &except_fds)) {
127
0
        flags |= ARES_EVENT_FLAG_READ;
128
0
      }
129
130
0
      if (FD_ISSET(fdlist[i], &write_fds)) {
131
0
        flags |= ARES_EVENT_FLAG_WRITE;
132
0
      }
133
134
0
      if (flags == 0) {
135
0
        continue;
136
0
      }
137
138
0
      cnt++;
139
140
0
      ev->cb(e, fdlist[i], ev->data, flags);
141
0
    }
142
0
  }
143
144
0
  ares_free(fdlist);
145
146
0
  return cnt;
147
0
}
148
149
const ares_event_sys_t ares_evsys_select = {
150
  "select",
151
  ares_evsys_select_init,
152
  ares_evsys_select_destroy,   /* NoOp */
153
  ares_evsys_select_event_add, /* NoOp */
154
  ares_evsys_select_event_del, /* NoOp */
155
  ares_evsys_select_event_mod, /* NoOp */
156
  ares_evsys_select_wait
157
};
158
159
#endif