Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qpoll.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qcore_unix_p.h"
5
6#ifdef Q_OS_RTEMS
7#include <rtems/rtems_bsdnet_internal.h>
8#endif
9
11
12#define QT_POLL_READ_MASK (POLLIN | POLLRDNORM)
13#define QT_POLL_WRITE_MASK (POLLOUT | POLLWRNORM | POLLWRBAND)
14#define QT_POLL_EXCEPT_MASK (POLLPRI | POLLRDBAND)
15#define QT_POLL_ERROR_MASK (POLLERR | POLLNVAL)
16#define QT_POLL_EVENTS_MASK (QT_POLL_READ_MASK | QT_POLL_WRITE_MASK | QT_POLL_EXCEPT_MASK)
17
18static inline int qt_poll_prepare(struct pollfd *fds, nfds_t nfds,
19 fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
20{
21 int max_fd = -1;
22
23 FD_ZERO(read_fds);
24 FD_ZERO(write_fds);
25 FD_ZERO(except_fds);
26
27 for (nfds_t i = 0; i < nfds; i++) {
28 if (fds[i].fd >= FD_SETSIZE) {
29 errno = EINVAL;
30 return -1;
31 }
32
33 if ((fds[i].fd < 0) || (fds[i].revents & QT_POLL_ERROR_MASK))
34 continue;
35
36 if (fds[i].events & QT_POLL_READ_MASK)
37 FD_SET(fds[i].fd, read_fds);
38
39 if (fds[i].events & QT_POLL_WRITE_MASK)
40 FD_SET(fds[i].fd, write_fds);
41
42 if (fds[i].events & QT_POLL_EXCEPT_MASK)
43 FD_SET(fds[i].fd, except_fds);
44
45 if (fds[i].events & QT_POLL_EVENTS_MASK)
46 max_fd = qMax(max_fd, fds[i].fd);
47 }
48
49 return max_fd + 1;
50}
51
52static inline void qt_poll_examine_ready_read(struct pollfd &pfd)
53{
54 int res;
55 char data;
56
57 QT_EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK));
58 const int error = (res < 0) ? errno : 0;
59
60 if (res == 0) {
61 pfd.revents |= POLLHUP;
62 } else if (res > 0 || error == ENOTSOCK || error == ENOTCONN) {
63 pfd.revents |= QT_POLL_READ_MASK & pfd.events;
64 } else {
65 switch (error) {
66 case ESHUTDOWN:
67 case ECONNRESET:
68 case ECONNABORTED:
69 case ENETRESET:
70 pfd.revents |= POLLHUP;
71 break;
72 default:
73 pfd.revents |= POLLERR;
74 break;
75 }
76 }
77}
78
79static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds,
80 fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
81{
82 int result = 0;
83
84 for (nfds_t i = 0; i < nfds; i++) {
85 if (fds[i].fd < 0)
86 continue;
87
88 if (FD_ISSET(fds[i].fd, read_fds))
90
91 if (FD_ISSET(fds[i].fd, write_fds))
92 fds[i].revents |= QT_POLL_WRITE_MASK & fds[i].events;
93
94 if (FD_ISSET(fds[i].fd, except_fds))
95 fds[i].revents |= QT_POLL_EXCEPT_MASK & fds[i].events;
96
97 if (fds[i].revents != 0)
98 result++;
99 }
100
101 return result;
102}
103
104static inline bool qt_poll_is_bad_fd(int fd)
105{
106#ifdef Q_OS_RTEMS
107 if (!rtems_bsdnet_fdToSocket(fd))
108 return true;
109#endif
110
111 int ret;
112 QT_EINTR_LOOP(ret, fcntl(fd, F_GETFD));
113 return (ret == -1 && errno == EBADF);
114}
115
116static inline int qt_poll_mark_bad_fds(struct pollfd *fds, const nfds_t nfds)
117{
118 int n_marked = 0;
119
120 for (nfds_t i = 0; i < nfds; i++) {
121 if (fds[i].fd < 0)
122 continue;
123
124 if (fds[i].revents & QT_POLL_ERROR_MASK)
125 continue;
126
127 if (qt_poll_is_bad_fd(fds[i].fd)) {
128 fds[i].revents |= POLLNVAL;
129 n_marked++;
130 }
131 }
132
133 return n_marked;
134}
135
136int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
137{
138 if (!fds && nfds) {
139 errno = EFAULT;
140 return -1;
141 }
142
143 fd_set read_fds, write_fds, except_fds;
144 struct timeval tv, *ptv = nullptr;
145
146 if (timeout_ts) {
147 tv = timespecToTimeval(*timeout_ts);
148 ptv = &tv;
149 }
150
151 int n_bad_fds = 0;
152
153 for (nfds_t i = 0; i < nfds; i++) {
154 fds[i].revents = 0;
155
156 if (fds[i].fd < 0)
157 continue;
158
159 if (fds[i].fd > FD_SETSIZE) {
160 errno = EINVAL;
161 return -1;
162 }
163
164 if (fds[i].events & QT_POLL_EVENTS_MASK)
165 continue;
166
167 if (qt_poll_is_bad_fd(fds[i].fd)) {
168 // Mark bad file descriptors that have no event flags set
169 // here, as we won't be passing them to select below and therefore
170 // need to do the check ourselves
171 fds[i].revents = POLLNVAL;
172 n_bad_fds++;
173 }
174 }
175
176 forever {
177 const int max_fd = qt_poll_prepare(fds, nfds, &read_fds, &write_fds, &except_fds);
178
179 if (max_fd < 0)
180 return max_fd;
181
182 if (n_bad_fds > 0) {
183 tv.tv_sec = 0;
184 tv.tv_usec = 0;
185 ptv = &tv;
186 }
187
188 const int ret = ::select(max_fd, &read_fds, &write_fds, &except_fds, ptv);
189
190 if (ret == 0)
191 return n_bad_fds;
192
193 if (ret > 0)
194 return qt_poll_sweep(fds, nfds, &read_fds, &write_fds, &except_fds);
195
196 if (errno != EBADF)
197 return -1;
198
199 // We have at least one bad file descriptor that we waited on, find out which and try again
200 n_bad_fds += qt_poll_mark_bad_fds(fds, nfds);
201 }
202}
203
EGLint EGLint EGLint EGLint int int int int * fds
Combined button and popup list for selecting options.
#define QT_EINTR_LOOP(var, cmd)
timeval timespecToTimeval(timespec ts)
DBusConnection const char DBusError * error
#define forever
Definition qforeach.h:78
return ret
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint64 GLenum GLint fd
GLuint res
GLuint64EXT * result
[6]
int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
Definition qpoll.cpp:136
static int qt_poll_prepare(struct pollfd *fds, nfds_t nfds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
Definition qpoll.cpp:18
static void qt_poll_examine_ready_read(struct pollfd &pfd)
Definition qpoll.cpp:52
#define QT_POLL_READ_MASK
Definition qpoll.cpp:12
#define QT_POLL_ERROR_MASK
Definition qpoll.cpp:15
#define QT_POLL_EVENTS_MASK
Definition qpoll.cpp:16
#define QT_POLL_EXCEPT_MASK
Definition qpoll.cpp:14
static int qt_poll_mark_bad_fds(struct pollfd *fds, const nfds_t nfds)
Definition qpoll.cpp:116
static int qt_poll_sweep(struct pollfd *fds, nfds_t nfds, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
Definition qpoll.cpp:79
static bool qt_poll_is_bad_fd(int fd)
Definition qpoll.cpp:104
#define QT_POLL_WRITE_MASK
Definition qpoll.cpp:13
selection select(topLeft, bottomRight)