Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | | - |
18 | | - |
19 | | - |
20 | | - |
21 | | - |
22 | | - |
23 | | - |
24 | | - |
25 | | - |
26 | | - |
27 | | - |
28 | | - |
29 | | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | | - |
35 | | - |
36 | | - |
37 | | - |
38 | | - |
39 | | - |
40 | | - |
41 | #include "qplatformdefs.h" | - |
42 | | - |
43 | #include "qcoreapplication.h" | - |
44 | #include "qpair.h" | - |
45 | #include "qsocketnotifier.h" | - |
46 | #include "qthread.h" | - |
47 | #include "qelapsedtimer.h" | - |
48 | | - |
49 | #include "qeventdispatcher_unix_p.h" | - |
50 | #include <private/qthread_p.h> | - |
51 | #include <private/qcoreapplication_p.h> | - |
52 | #include <private/qcore_unix_p.h> | - |
53 | | - |
54 | #include <errno.h> | - |
55 | #include <stdio.h> | - |
56 | #include <stdlib.h> | - |
57 | | - |
58 | #ifndef QT_NO_EVENTFD | - |
59 | # include <sys/eventfd.h> | - |
60 | #endif | - |
61 | | - |
62 | | - |
63 | #if defined(Q_OS_VXWORKS) | - |
64 | # if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) | - |
65 | # undef _POSIX_MONOTONIC_CLOCK | - |
66 | # define _POSIX_MONOTONIC_CLOCK 1 | - |
67 | # endif | - |
68 | # include <pipeDrv.h> | - |
69 | # include <selectLibsys/time.h> | - |
70 | #endif | - |
71 | | - |
72 | #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) | - |
73 | # include <sys/times.h> | - |
74 | #endif | - |
75 | | - |
76 | QT_BEGIN_NAMESPACE | - |
77 | | - |
78 | static const char *socketType(QSocketNotifier::Type type) | - |
79 | { | - |
80 | switch (type) { | - |
81 | case QSocketNotifier::Read: never executed: case QSocketNotifier::Read: | 0 |
82 | return "Read"; never executed: return "Read"; | 0 |
83 | case QSocketNotifier::Write: never executed: case QSocketNotifier::Write: | 0 |
84 | return "Write"; never executed: return "Write"; | 0 |
85 | case QSocketNotifier::Exception: never executed: case QSocketNotifier::Exception: | 0 |
86 | return "Exception"; never executed: return "Exception"; | 0 |
87 | } | - |
88 | | - |
89 | Q_UNREACHABLE(); | - |
90 | } never executed: end of block | 0 |
91 | | - |
92 | QThreadPipe::QThreadPipe() | - |
93 | { | - |
94 | fds[0] = -1; | - |
95 | fds[1] = -1; | - |
96 | #if defined(Q_OS_INTEGRITYQ_OS_VXWORKS) | - |
97 | ||name[0] = '\0'; | - |
98 | #endif | - |
99 | } never executed: end of block | 0 |
100 | | - |
101 | QThreadPipe::~QThreadPipe() | - |
102 | { | - |
103 | if (fds[0] >= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
104 | close(fds[0]); never executed: close(fds[0]); | 0 |
105 | | - |
106 | if (fds[1] >= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
107 | close(fds[1]); never executed: close(fds[1]); | 0 |
108 | | - |
109 | #if defined(Q_OS_VXWORKS) | - |
110 | pipeDevDelete(name, true); | - |
111 | #endif | - |
112 | } never executed: end of block | 0 |
113 | | - |
114 | #if defined(Q_OS_VXWORKS) | - |
115 | static void initThreadPipeFD(int fd) | - |
116 | { | - |
117 | int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); | - |
118 | if (ret == -1) | - |
119 | perror("QEventDispatcherUNIXPrivate: Unable to init thread pipe"); | - |
120 | | - |
121 | int flags = fcntl(fd, F_GETFL); | - |
122 | if (flags == -1) | - |
123 | perror("QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe"); | - |
124 | | - |
125 | ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); | - |
126 | if (ret == -1) | - |
127 | perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe"); | - |
128 | } | - |
129 | #endif | - |
130 | | - |
| QEventDispatcherUNIXPrivatebool QThreadPipe::QEventDispatcherUNIXPrivateinit() | |
132 | { | - |
| extern Qt::HANDLE qt_application_thread_id; | |
| mainThread = (QThread::currentThreadId() == qt_application_thread_id); | |
| bool pipefail = false; | |
| | |
| #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) | |
134 | | - |
| #elif defined(Q_OS_INTEGRITY) | |
| if (socketpair(AF_INET, SOCK_STREAM, 0, thread_pipe) == -1) { | |
| perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); | |
| pipefail = true; | |
| } else { | |
| initThreadPipeFD(thread_pipe[0]); | |
| initThreadPipeFD(thread_pipe[1]); | |
| }#elif defined(Q_OS_VXWORKS) | |
136 | char name[20];qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf())); | - |
137 | | - |
138 | | - |
139 | pipeDevDelete(name, true); | - |
140 | | - |
141 | | - |
142 | if (pipeDevCreate(name, 128 , 1 ) != OK) { | - |
143 | perror("QEventDispatcherUNIXPrivate():"QThreadPipe: Unable to create thread pipe device"device %s", name); | - |
144 | pipefail = truereturn false; | - |
145 | } | - |
146 | | - |
147 | else {if ((thread_pipefds[0] = open(name, O_RDWR, 0)) < 0) { | - |
148 | perror("QEventDispatcherUNIXPrivate():"QThreadPipe: Unable to createopen threadpipe pipe"device %s", name); | - |
149 | pipefail = truereturn false; | - |
150 | } | - |
151 | | - |
152 | else {initThreadPipeFD(thread_pipefds[0]); | - |
153 | thread_pipefds[1] = thread_pipefds[0]; | - |
| } | |
| }#else | |
155 | # ifndef QT_NO_EVENTFD | - |
156 | thread_pipeif ((fds[0] = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| if (thread_pipe[TRUE | never evaluated | FALSE | never evaluated |
)) >= 0] != -1)TRUE | never evaluated | FALSE | never evaluated |
| |
157 | thread_pipe[1] = -1return true; never executed: return true; | 0 |
| else # endif | |
159 | if (qt_safe_pipe(thread_pipefds, O_NONBLOCK) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
160 | perror("QEventDispatcherUNIXPrivate():"QThreadPipe: Unable to create thread pipe"); | - |
161 | pipefail = truereturn false; never executed: return false; | 0 |
162 | } | - |
163 | #endif | - |
164 | | - |
165 | if (pipefail) never executed: return true; | 0 |
| qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); never executed: return true; | |
| | |
| sn_highest = -1 never executed: return true; return true;never executed: return true; | |
166 | } | - |
167 | | - |
| QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivatepollfd QThreadPipe::prepare() const | |
169 | { | - |
170 | #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY) never executed: return qt_make_pollfd(fds[0], 0x001); | 0 |
| #elif defined(Q_OS_VXWORKS) never executed: return qt_make_pollfd(fds[0], 0x001); | |
| close(thread_pipe[0]); never executed: return qt_make_pollfd(fds[0], 0x001); | |
| | |
| char name[20]; never executed: return qt_make_pollfd(fds[0], 0x001); | |
| qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf())); never executed: return qt_make_pollfd(fds[0], 0x001); | |
| | |
| pipeDevDelete(name, true); never executed: return qt_make_pollfd(fds[0], 0x001); | |
| #else never executed: return qt_make_pollfd(fds[0], 0x001); | |
| close never executed: return qt_make_pollfd(fds[0], 0x001); return qt_make_pollfd(thread_pipefds[0]);never executed: return qt_make_pollfd(fds[0], 0x001); | |
| if (thread_pipe[1] != -1) never executed: return qt_make_pollfd(fds[0], 0x001); | |
| close(thread_pipe[1]); never executed: return qt_make_pollfd(fds[0], 0x001); | |
| #endif never executed: return qt_make_pollfd(fds[0], 0x001); | |
| | |
| qDeleteAll(timerList never executed: return qt_make_pollfd(fds[0], 0x001); ], POLLIN);never executed: return qt_make_pollfd(fds[0], 0x001); | |
171 | } | - |
172 | | - |
| int QEventDispatcherUNIXPrivate::doSelect(QEventLoopvoid QThreadPipe::ProcessEventsFlags flags, timespec *timeout) | |
| { | |
| Q_Q(QEventDispatcherUNIX); | |
| | |
| timerList.updateCurrentTime(); | |
| | |
| int nsel; | |
| dowakeUp() | |
174 | { | - |
175 | int highest = 0;if (!(flags & QEventLoop::ExcludeSocketNotifiers) &&wakeUps.testAndSetAcquire(sn_highest >= 0)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| sn_vec[0].select_fds = sn_vec[TRUE | never evaluated | FALSE | never evaluated |
0].enabled_fds;TRUE | never evaluated | FALSE | never evaluated |
| |
| sn_vec[1].select_fds = sn_vec[TRUE | never evaluated | FALSE | never evaluated |
, 1].enabled_fds;TRUE | never evaluated | FALSE | never evaluated |
| |
| sn_vec[2].select_fds = sn_vec[2].enabled_fds;TRUE | never evaluated | FALSE | never evaluated |
| |
| highest = sn_highest;TRUE | never evaluated | FALSE | never evaluated |
| |
| } elseTRUE | never evaluated | FALSE | never evaluated |
)) {TRUE | never evaluated | FALSE | never evaluated |
| |
| FD_ZERO(&sn_vec[0].select_fds); | |
| FD_ZERO(&sn_vec[1].select_fds); | |
| FD_ZERO(&sn_vec[2].select_fds); | |
| } | |
| | |
| int wakeUpFd = initThreadWakeUp(); | |
| highest = qMax(highest, wakeUpFd); | |
| | |
| nsel = q->select#ifndef QT_NO_EVENTFD | |
177 | ifTRUE | never evaluated | FALSE | never evaluated |
(highest + 1,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| &sn_vec[0].select_fds,TRUE | never evaluated | FALSE | never evaluated |
| |
| &sn_vec[1].select_fds,TRUE | never evaluated | FALSE | never evaluated |
| |
| &sn_vecTRUE | never evaluated | FALSE | never evaluated |
fds[2].select_fds,TRUE | never evaluated | FALSE | never evaluated |
| |
| timeout);TRUE | never evaluated | FALSE | never evaluated |
| |
| } while (nsel == -TRUE | never evaluated | FALSE | never evaluated |
1&& (errno == EINTR || errno == EAGAIN));TRUE | never evaluated | FALSE | never evaluated |
| |
| | |
| if (nselTRUE | never evaluated | FALSE | never evaluated |
] == -1) {TRUE | never evaluated | FALSE | never evaluated |
| |
| if (errno == EBADF) {TRUE | never evaluated | FALSE | never evaluated |
| |
| fd_set fdset;TRUE | never evaluated | FALSE | never evaluated |
| |
| timeval tm;TRUE | never evaluated | FALSE | never evaluated |
| |
| tm.tv_sec = tm.tv_usec = 0l;TRUE | never evaluated | FALSE | never evaluated |
| |
| | |
| for (int type = 0; type < 3; ++typeTRUE | never evaluated | FALSE | never evaluated |
) {TRUE | never evaluated | FALSE | never evaluated |
| |
178 | QSockNotType::List &list = sn_vec[type].list; | - |
| if (list.size() == 0) | |
| continue; | |
| | |
| for (int i | |
179 | eventfd_t value = 01; | - |
180 | i < list.size(); ++i) { | - |
| QSockNot *sn = list[i]; | |
| | |
| FD_ZERO(&fdset); | |
| FD_SET(sn->fd, &fdset);int ret= -1; | |
181 | do { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| switch never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
EINTR_LOOP(type) {never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| case 0: never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
ret= select(sn->fd + 1, &fdset, 0, 0, &tm);never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| break; never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| case 1: ret = select never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
eventfd_write(sn->fd + 1, 0, &fdset,fds[0, &tm);never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| break never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
], value));never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
182 | return never executed: return; ;never executed: return; | 0 |
183 | case 2: ret} | - |
184 | #endif | - |
185 | char c = select(sn->fd + 1, 0,0, &fdset, &tm); | - |
| break; | |
186 | } | - |
| } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); | |
| | |
| ifqt_safe_write(ret == -fds[1&& errno == EBADF) { | |
| static const char *t[] = { "Read", "Write", "Exception" }; | |
| qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...", | |
| sn->fd], &c, t[type]); | |
| sn->obj->setEnabled(false); | |
| } | |
| } | |
| } | |
| } else { | |
| perror("select"1); | |
187 | } never executed: end of block | 0 |
188 | } never executed: end of block | 0 |
189 | | - |
| int nevents = processThreadWakeUp(nsel); | |
| | |
| if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) { | |
| for (int i=0; i<3; i++) { | |
| QSockNotTypeQThreadPipe::List &list = sn_vec[i].list; | |
| forcheck(int j = 0; j < list.size(); ++jconst pollfd &pfd) | |
191 | { | - |
192 | QSockNot *sn = list[j]; | - |
| if (FD_ISSETQ_ASSERT(sn->pfd.fd , &sn_vec[i].select_fds)) | |
| q->setSocketNotifierPending(sn->obj); | |
| } | |
| } | |
| } | |
| return (nevents + q->activateSocketNotifiers()); | |
| } | |
| | |
| int QEventDispatcherUNIXPrivate::initThreadWakeUp() | |
| { | |
| FD_SET(thread_pipe[0], &sn_vec== fds[0].select_fds); | |
| return thread_pipe]); | |
193 | | - |
194 | char c[016]; | - |
195 | } | - |
| | |
| int QEventDispatcherUNIXPrivate::processThreadWakeUp(const int nsel) | |
| {readyread = pfd.revents & POLLIN; | |
196 | | - |
197 | if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds))readyread) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
198 | | - |
199 | | - |
200 | #if defined(Q_OS_VXWORKS) | - |
201 | char c[16];::read(thread_pipefds[0], c, sizeof(c)); | - |
202 | ::ioctl(thread_pipefds[0], FIOFLUSH, 0); | - |
203 | #else | - |
204 | # ifndef QT_NO_EVENTFD | - |
205 | if (thread_pipefds[1] == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
206 | | - |
207 | eventfd_t value; | - |
208 | eventfd_read(thread_pipefds[0], &value); | - |
209 | } else never executed: end of block | 0 |
210 | # endif | - |
211 | { | - |
212 | char c[16];while (::read(thread_pipefds[0], c, sizeof(c)) > 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| } never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
{}never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| |
213 | } never executed: end of block | 0 |
214 | #endif | - |
215 | | - |
216 | if (!wakeUps.testAndSetRelease(1, 0)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
217 | | - |
218 | qWarning("QEventDispatcherUNIX"QThreadPipe: internal error, wakeUps.testAndSetRelease(1, 0) failed!"); | - |
219 | } never executed: end of block | 0 |
220 | } never executed: end of block | 0 |
221 | | - |
222 | return 1readyread; never executed: return readyread; | 0 |
223 | } | - |
224 | | - |
225 | QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() | - |
226 | { | - |
227 | if (Q_UNLIKELY(threadPipe.init() == false))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
228 | qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); never executed: QMessageLogger(__FILE__, 228, __PRETTY_FUNCTION__).fatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); | 0 |
229 | } never executed: end of block | 0 |
230 | | - |
231 | QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() | - |
232 | { | - |
233 | | - |
234 | qDeleteAll(timerList); | - |
235 | } never executed: end of block | 0 |
236 | | - |
237 | void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier) | - |
238 | { | - |
239 | Q_ASSERT(notifier); | - |
240 | | - |
241 | if (pendingNotifiers.contains(notifier))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
242 | return; never executed: return; | 0 |
243 | | - |
244 | pendingNotifiers << notifier; | - |
245 | } never executed: end of block | 0 |
246 | | - |
247 | int QEventDispatcherUNIXPrivate::activateTimers() | - |
248 | { | - |
249 | return timerList.activateTimers(); never executed: return timerList.activateTimers(); | 0 |
250 | } | - |
251 | | - |
252 | void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers() | - |
253 | { | - |
254 | for (const pollfd &pfd : qAsConst(pollfds)) { | - |
255 | if (pfd.fd < 0 || pfd.revents == 0)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
256 | continue; never executed: continue; | 0 |
257 | | - |
258 | auto it = socketNotifiers.find(pfd.fd); | - |
259 | Q_ASSERT(it != socketNotifiers.end()); | - |
260 | | - |
261 | const QSocketNotifierSetUNIX &sn_set = it.value(); | - |
262 | | - |
263 | static const struct { | - |
264 | QSocketNotifier::Type type; | - |
265 | short flags; | - |
266 | } notifiers[] = { | - |
267 | { QSocketNotifier::Read, POLLIN | POLLHUP | POLLERR }, | - |
268 | { QSocketNotifier::Write, POLLOUT | POLLHUP | POLLERR }, | - |
269 | { QSocketNotifier::Exception, POLLPRI | POLLHUP | POLLERR } | - |
270 | }; | - |
271 | | - |
272 | for (const auto &n : notifiers) { | - |
273 | QSocketNotifier *notifier = sn_set.notifiers[n.type]; | - |
274 | | - |
275 | if (!notifier)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
276 | continue never executed: continue; ;never executed: continue; | 0 |
277 | | - |
278 | if (pfd.revents & POLLNVAL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
279 | qWarning("QSocketNotifier: Invalid socket %d with type %s, disabling...", | - |
280 | it.key(), socketType(n.type)); | - |
281 | notifier->setEnabled(false); | - |
282 | } never executed: end of block | 0 |
283 | | - |
284 | if (pfd.revents & n.flags)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
285 | setSocketNotifierPending(notifier); never executed: setSocketNotifierPending(notifier); | 0 |
286 | } never executed: end of block | 0 |
287 | } never executed: end of block | 0 |
288 | | - |
289 | pollfds.clear(); | - |
290 | } never executed: end of block | 0 |
291 | | - |
292 | int QEventDispatcherUNIXPrivate::activateSocketNotifiers() | - |
293 | { | - |
294 | markPendingSocketNotifiers(); | - |
295 | | - |
296 | if (pendingNotifiers.isEmpty())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
297 | return 0; never executed: return 0; | 0 |
298 | | - |
299 | int n_activated = 0; | - |
300 | QEvent event(QEvent::SockAct); | - |
301 | | - |
302 | while (!pendingNotifiers.isEmpty()) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
303 | QSocketNotifier *notifier = pendingNotifiers.takeFirst(); | - |
304 | QCoreApplication::sendEvent(notifier, &event); | - |
305 | ++n_activated; | - |
306 | } never executed: end of block | 0 |
307 | | - |
308 | return n_activated never executed: return n_activated; ;never executed: return n_activated; | 0 |
309 | } | - |
310 | | - |
311 | QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent) | - |
312 | : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent) | - |
313 | { } | - |
314 | | - |
315 | QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent) | - |
316 | : QAbstractEventDispatcher(dd, parent) | - |
317 | { } | - |
318 | | - |
319 | QEventDispatcherUNIX::~QEventDispatcherUNIX() | - |
| { | |
| } | |
| | |
| int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, | |
| timespec *timeout){ return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);} | |
321 | | - |
322 | | - |
323 | | - |
324 | | - |
325 | void QEventDispatcherUNIX::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *obj) | - |
326 | { | - |
327 | #ifndef QT_NO_DEBUG | - |
328 | if (timerId < 1 || interval < 0 || !obj) { | - |
329 | qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments"); | - |
330 | return; | - |
331 | } else if (obj->thread() != thread() || thread() != QThread::currentThread()) { | - |
332 | qWarning("QEventDispatcherUNIX::registerTimer: timers cannot be started from another thread"); | - |
333 | return; | - |
334 | } | - |
335 | #endif | - |
336 | | - |
337 | Q_D(QEventDispatcherUNIX); | - |
338 | d->timerList.registerTimer(timerId, interval, timerType, obj); | - |
339 | } | - |
340 | | - |
341 | | - |
342 | | - |
343 | | - |
344 | bool QEventDispatcherUNIX::unregisterTimer(int timerId) | - |
345 | { | - |
346 | #ifndef QT_NO_DEBUG | - |
347 | if (timerId < 1) { | - |
348 | qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument"); | - |
349 | return false; | - |
350 | } else if (thread() != QThread::currentThread()) { | - |
351 | qWarning("QEventDispatcherUNIX::unregisterTimer: timers cannot be stopped from another thread"); | - |
352 | return false; | - |
353 | } | - |
354 | #endif | - |
355 | | - |
356 | Q_D(QEventDispatcherUNIX); | - |
357 | return d->timerList.unregisterTimer(timerId); | - |
358 | } | - |
359 | | - |
360 | | - |
361 | | - |
362 | | - |
363 | bool QEventDispatcherUNIX::unregisterTimers(QObject *object) | - |
364 | { | - |
365 | #ifndef QT_NO_DEBUG | - |
366 | if (!object) { | - |
367 | qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument"); | - |
368 | return false; | - |
369 | } else if (object->thread() != thread() || thread() != QThread::currentThread()) { | - |
370 | qWarning("QEventDispatcherUNIX::unregisterTimers: timers cannot be stopped from another thread"); | - |
371 | return false; | - |
372 | } | - |
373 | #endif | - |
374 | | - |
375 | Q_D(QEventDispatcherUNIX); | - |
376 | return d->timerList.unregisterTimers(object); | - |
377 | } | - |
378 | | - |
379 | QList<QEventDispatcherUNIX::TimerInfo> | - |
380 | QEventDispatcherUNIX::registeredTimers(QObject *object) const | - |
381 | { | - |
382 | if (!object) { | - |
383 | qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument"); | - |
384 | return QList<TimerInfo>(); | - |
385 | } | - |
386 | | - |
387 | Q_D(const QEventDispatcherUNIX); | - |
388 | return d->timerList.registeredTimers(object); | - |
| } | |
| | |
| QSockNotType::QSockNotType() | |
| { | |
| FD_ZERO(&select_fds); | |
| FD_ZERO(&enabled_fds); | |
| FD_ZERO(&pending_fds); | |
| } | |
| | |
| QSockNotType::~QSockNotType() | |
| { | |
| for (int i = 0; i < list.size(); ++i) | |
| delete list[i];} | |
390 | | - |
391 | | - |
392 | | - |
393 | | - |
394 | | - |
395 | void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier) | - |
396 | { | - |
397 | Q_ASSERT(notifier); | - |
398 | int sockfd = notifier->socket(); | - |
399 | intQSocketNotifier::Type type = notifier->type(); | - |
400 | #ifndef QT_NO_DEBUG | - |
401 | if (sockfd < 0TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| || unsigned(sockfd) >= FD_SETSIZE) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| qWarning("QSocketNotifier: Internal error");TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| return;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| } elseTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
if (notifier->thread() != thread() || thread() != QThread::currentThread()) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
402 | qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread"); | - |
403 | return; never executed: return; | 0 |
404 | } | - |
405 | #endif | - |
406 | | - |
407 | Q_D(QEventDispatcherUNIX); | - |
408 | QSockNotType::List &listQSocketNotifierSetUNIX &sn_set = d->sn_vec[type].list; | - |
| fd_set *fds = &d->sn_vecsocketNotifiers[type].enabled_fds; | |
| QSockNot *sn; | |
| | |
| sn = new QSockNot; | |
| sn->obj = notifier; | |
| sn->fd =sockfd; | |
| sn->queue = &d->sn_vec]; | |
409 | | - |
410 | if (sn_set.notifiersTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
[type].pending_fds;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| | |
| int i;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| for (i = 0; i < listTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
] && sn_set.size(); ++i) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| QSockNot *p = listTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
notifiers[i];TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| if (p->fd < sockfd)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| break;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| if (p->fd == sockfdTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
type] != notifier)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
411 | { never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | 0 |
| static const char *t[] = { "Read", "Write", "Exception" }; never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); qWarning("QSocketNotifier"%s: Multiple socket notifiers for"never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | |
| "same never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); same socket %d and type %s",never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | |
412 | Q_FUNC_INFO never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); , sockfd, t[socketType(type]);never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | 0 |
| } never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | |
| } never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | |
| list never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); ));never executed: QMessageLogger(__FILE__, 411, __PRETTY_FUNCTION__).warning("%s: Multiple socket notifiers for same socket %d and type %s", __PRETTY_FUNCTION__, sockfd, socketType(type)); | |
413 | | - |
414 | sn_set.insert(i, sn); | - |
| | |
| FD_SET(sockfd, fds); | |
| d->sn_highestnotifiers[type] = qMax(d->sn_highest, sockfd);notifier; | |
415 | } never executed: end of block | 0 |
416 | | - |
417 | void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier) | - |
418 | { | - |
419 | Q_ASSERT(notifier); | - |
420 | int sockfd = notifier->socket(); | - |
421 | intQSocketNotifier::Type type = notifier->type(); | - |
422 | #ifndef QT_NO_DEBUG | - |
423 | if (sockfd < 0TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| || unsigned(sockfd) >= FD_SETSIZE) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| qWarning("QSocketNotifier: Internal error");TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| return;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
| } elseTRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
if (notifier->thread() != thread() || thread() != QThread::currentThread()) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| |
424 | qWarning("QSocketNotifier: socket notifiersnotifier (fd %d) cannot be disabled from another thread"); | - |
| return; | |
| } | |
| #endif | |
| | |
| Q_D(QEventDispatcherUNIX); | |
| QSockNotType::List &list = d->sn_vec[type].list; | |
| fd_set *fds = &d->sn_vec[type].enabled_fds; | |
| QSockNot *sn = 0; | |
| int i; | |
| for (i = 0; i < listthread.size(); ++i) { | |
| sn = list[i]; | |
| if\n" | |
425 | "(sn->obj == notifier && sn->fd == sockfd) | - |
| break; | |
| } | |
| ifNotifier's thread is %s(i == list.size()) return; | |
| | |
| FD_CLR%p), event dispatcher's thread is %s(sockfd, fds); FD_CLR%p), current thread is %s(sockfd%p))", | |
426 | sn->queue); | - |
| d->sn_pending_list.removeAll(sn); list.removeAt(i); delete sn; | |
| | |
| if (d->sn_highest ==sockfd) { d->sn_highest = -1; | |
| for (int i=0; i<3; i++) { | |
| if (!d->sn_vec[i].list.isEmpty()) | |
| d->sn_highest = qMax(d->sn_highest, | |
427 | d->sn_vec[i].list[0]->fd); | - |
| } | |
| } | |
| } | |
| | |
| void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier) | |
| { | |
| Q_ASSERT(notifier); | |
| int sockfd =notifier->socket(); | |
| int type =thread() ? notifier->type(); | |
| #ifndef QT_NO_DEBUG | |
| if (sockfd < 0 | |
| || unsigned(sockfd) >= FD_SETSIZE) { | |
| qWarning("QSocketNotifierthread()->metaObject()->className() : Internal error"); | |
| return; | |
| } | |
| Q_ASSERT("QThread", notifier->thread(), | |
428 | thread() ==? thread()->metaObject()->className() &&: "QThread", thread(), | - |
429 | QThread::currentThread() ==? QThread::currentThread()->metaObject()->className() : "QThread", QThread::currentThread()); | - |
430 | return; never executed: return; | 0 |
431 | } | - |
432 | #endif | - |
433 | | - |
434 | Q_D(QEventDispatcherUNIX); | - |
435 | | - |
436 | QSockNotType::List &list =d->sn_vec[type].list; | - |
| QSockNot *sn = 0; | |
| int i; | |
| forpendingNotifiers.removeOne(notifier); | |
437 | | - |
438 | auto i = 0; i < listd->socketNotifiers.size(); ++i) { | - |
| sn = list[i]; | |
| iffind(sn->obj == notifier && sn->fd ==sockfd) | |
| break; | |
| }); | |
439 | if (i == list.size()) return;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| | |
| if (! FD_ISSET(sn->fd, sn->queue)) {TRUE | never evaluated | FALSE | never evaluated |
| |
| if (TRUE | never evaluated | FALSE | never evaluated |
d->sn_pending_listsocketNotifiers.isEmptyend())TRUE | never evaluated | FALSE | never evaluated |
| |
440 | { never executed: return; | 0 |
| d->sn_pending_list never executed: return; return;never executed: return; | |
441 | | - |
442 | QSocketNotifierSetUNIX &sn_set = i.appendvalue(); | - |
443 | | - |
444 | ifTRUE | never evaluated | FALSE | never evaluated |
(sn);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| } else {TRUE | never evaluated | FALSE | never evaluated |
| |
| d->sn_pending_listTRUE | never evaluated | FALSE | never evaluated |
sn_set.insert((qrand() & 0xffnotifiers[type] == nullptr)TRUE | never evaluated | FALSE | never evaluated |
| |
445 | %return; never executed: return; | 0 |
446 | | - |
447 | ifTRUE | never evaluated | FALSE | never evaluated |
(d->sn_pending_listsn_set.size()+1), sn);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| }TRUE | never evaluated | FALSE | never evaluated |
| |
| FD_SET(sn->fd, sn->queue);TRUE | never evaluated | FALSE | never evaluated |
| |
| }TRUE | never evaluated | FALSE | never evaluated |
| |
| }TRUE | never evaluated | FALSE | never evaluated |
| |
| | |
| int QEventDispatcherUNIX::activateTimers()TRUE | never evaluated | FALSE | never evaluated |
notifiers[type] != notifier) {TRUE | never evaluated | FALSE | never evaluated |
| |
448 | Q_ASSERTqWarning(thread() == QThread::currentThread()); | - |
| Q_D"%s: Multiple socket notifiers for same socket %d and type %s", | |
449 | Q_FUNC_INFO, sockfd, socketType(QEventDispatcherUNIX);type)); | - |
450 | returnd->timerList.activateTimers();; never executed: return; | 0 |
451 | } | - |
452 | | - |
453 | int QEventDispatcherUNIX::activateSocketNotifiers() | - |
| { | |
| Q_D(QEventDispatcherUNIX); | |
| if (d->sn_pending_listsn_set.isEmpty()) | |
| return 0; | |
| | |
| int n_actnotifiers[type] = 0nullptr; | |
454 | | - |
455 | QEvent eventif (QEvent::SockAct);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| while (!d->sn_pending_listTRUE | never evaluated | FALSE | never evaluated |
sn_set.isEmpty())TRUE | never evaluated | FALSE | never evaluated |
| |
456 | { never executed: d->socketNotifiers.erase(i); | 0 |
| QSockNot *sn = never executed: d->socketNotifiers.erase(i); d->sn_pending_listsocketNotifiers.takeFirst();never executed: d->socketNotifiers.erase(i); | |
| if (FD_ISSET(sn->fd, sn->queue)) { never executed: d->socketNotifiers.erase(i); | |
| FD_CLR(sn->fd, sn->queue); never executed: d->socketNotifiers.erase(i); | |
| QCoreApplication::sendEvent never executed: d->socketNotifiers.erase(i); erase(sn->obj, &eventi);never executed: d->socketNotifiers.erase(i); | |
| ++n_act; never executed: end of block | |
| } never executed: end of block | |
| } never executed: end of block | |
| return n_act; never executed: end of block }never executed: end of block | |
458 | | - |
459 | bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) | - |
460 | { | - |
461 | Q_D(QEventDispatcherUNIX); | - |
462 | d->interrupt.store(0); | - |
463 | | - |
464 | | - |
465 | emit awake(); | - |
466 | QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData); | - |
467 | | - |
468 | int neventsconst bool include_timers = (flags & QEventLoop::X11ExcludeTimers) == 0; | - |
469 | const bool include_notifiers = (flags & QEventLoop::ExcludeSocketNotifiers) == 0; | - |
470 | const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents; | - |
471 | | - |
472 | const bool canWait = (d->threadData->canWaitLocked()TRUE | never evaluated | FALSE | never evaluated |
| 0 |
473 | && !d->interrupt.load()TRUE | never evaluated | FALSE | never evaluated |
| 0 |
474 | && (flags & QEventLoop::WaitForMoreEvents));wait_for_events);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
475 | | - |
476 | if (canWait)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
477 | emit aboutToBlock(); never executed: aboutToBlock(); | 0 |
478 | | - |
479 | if (!(d->interrupt.load())TRUE | never evaluated | FALSE | never evaluated |
| 0 |
480 | { never executed: return false; | 0 |
| never executed: return false; return false;never executed: return false; | |
481 | | - |
482 | timespec *tm = 0nullptr; | - |
483 | timespec wait_tm = { 0l0, 0l0 }; | - |
484 | | - |
485 | if (!(flags & QEventLoop::X11ExcludeTimers)) {if (!canWait || (include_timers && d->timerList.timerWait(wait_tm)))))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
486 | tm = &wait_tm; never executed: tm = &wait_tm; | 0 |
487 | | - |
488 | } | - |
| | |
| if (!canWait) {d->pollfds.clear(); | |
489 | d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0)); | - |
490 | | - |
491 | if (!tm(include_notifiers)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
492 | tmfor (auto it = &wait_tm;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
| | |
| tmTRUE | never evaluated | FALSE | never evaluated |
d->tv_secsocketNotifiers.cbegin(); it != d->socketNotifiers.cend(); ++it)TRUE | never evaluated | FALSE | never evaluated |
| |
493 | d->pollfds.append(qt_make_pollfd(it.key(), it.value().events())); never executed: d->pollfds.append(qt_make_pollfd(it.key(), it.value().events())); | 0 |
494 | | - |
495 | | - |
496 | d->pollfds.append(d->threadPipe.prepare()); | - |
497 | | - |
498 | int nevents = 0l0; | - |
499 | | - |
500 | tmswitch (qt_safe_poll(d->tv_nsec = 0lpollfds.data(), d->pollfds.size(), tm)) { | - |
501 | case -1: never executed: case -1: | 0 |
502 | perror("qt_safe_poll"); | - |
503 | break never executed: break; ;never executed: break; | 0 |
504 | }case 0: never executed: case 0: | 0 |
505 | break; never executed: break; | 0 |
506 | default: never executed: default: | 0 |
507 | nevents =+= d->doSelectthreadPipe.check(flags, tm); | - |
| | |
| d->pollfds.takeLast()); | |
508 | if (!(flags & QEventLoop::X11ExcludeTimers)) {include_notifiers)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
509 | nevents += activateTimersd->activateSocketNotifiers(); never executed: nevents += d->activateSocketNotifiers(); | 0 |
510 | }break; never executed: break; | 0 |
511 | } | - |
512 | | - |
513 | if (include_timers)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
514 | nevents += d->activateTimers(); never executed: nevents += d->activateTimers(); | 0 |
515 | | - |
516 | | - |
517 | return (nevents > 0); never executed: return (nevents > 0); | 0 |
518 | } | - |
519 | | - |
520 | bool QEventDispatcherUNIX::hasPendingEvents() | - |
521 | { | - |
522 | extern uint qGlobalPostedEventsCount(); | - |
523 | return qGlobalPostedEventsCount(); | - |
524 | } | - |
525 | | - |
526 | int QEventDispatcherUNIX::remainingTime(int timerId) | - |
527 | { | - |
528 | #ifndef QT_NO_DEBUG | - |
529 | if (timerId < 1) { | - |
530 | qWarning("QEventDispatcherUNIX::remainingTime: invalid argument"); | - |
531 | return -1; | - |
532 | } | - |
533 | #endif | - |
534 | | - |
535 | Q_D(QEventDispatcherUNIX); | - |
536 | return d->timerList.timerRemainingTime(timerId); | - |
537 | } | - |
538 | | - |
539 | void QEventDispatcherUNIX::wakeUp() | - |
540 | { | - |
541 | Q_D(QEventDispatcherUNIX); | - |
542 | if (d->wakeUpsthreadPipe.testAndSetAcquire(0, 1)) { | - |
| #ifndef QT_NO_EVENTFD | |
| if (d->thread_pipe[1] == -1) { | |
| eventfd_t value = 1; | |
| int ret; | |
| EINTR_LOOP(ret, eventfd_write(d->thread_pipe[0], value)); | |
| return; | |
| } | |
| #endif | |
| char c = 0; | |
| qt_safe_write( d->thread_pipe[1], &c, 1 ); | |
| }wakeUp(); | |
543 | } never executed: end of block | 0 |
544 | | - |
545 | void QEventDispatcherUNIX::interrupt() | - |
546 | { | - |
547 | Q_D(QEventDispatcherUNIX); | - |
548 | d->interrupt.store(1); | - |
549 | wakeUp(); | - |
550 | } | - |
551 | | - |
552 | void QEventDispatcherUNIX::flush() | - |
553 | { } | - |
554 | | - |
555 | QT_END_NAMESPACE | - |
| | |