Qt 4.8
qeventdispatcher_unix.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qplatformdefs.h"
43 
44 #include "qcoreapplication.h"
45 #include "qpair.h"
46 #include "qsocketnotifier.h"
47 #include "qthread.h"
48 #include "qelapsedtimer.h"
49 
51 #include <private/qthread_p.h>
52 #include <private/qcoreapplication_p.h>
53 #include <private/qcore_unix_p.h>
54 
55 #include <errno.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 
59 // VxWorks doesn't correctly set the _POSIX_... options
60 #if defined(Q_OS_VXWORKS)
61 # if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0)
62 # undef _POSIX_MONOTONIC_CLOCK
63 # define _POSIX_MONOTONIC_CLOCK 1
64 # endif
65 # include <pipeDrv.h>
66 # include <selectLib.h>
67 #endif
68 
69 #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
70 # include <sys/times.h>
71 #endif
72 
74 
76 
77 /*****************************************************************************
78  UNIX signal handling
79  *****************************************************************************/
80 
81 static sig_atomic_t signal_received;
82 static sig_atomic_t signals_fired[NSIG];
83 
84 static void signalHandler(int sig)
85 {
86  signals_fired[sig] = 1;
87  signal_received = 1;
88 }
89 
90 
91 #if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS)
92 static void initThreadPipeFD(int fd)
93 {
94  int ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
95  if (ret == -1)
96  perror("QEventDispatcherUNIXPrivate: Unable to init thread pipe");
97 
98  int flags = fcntl(fd, F_GETFL);
99  if (flags == -1)
100  perror("QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");
101 
102  ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
103  if (ret == -1)
104  perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");
105 }
106 #endif
107 
109 {
112  bool pipefail = false;
113 
114  // initialize the common parts of the event loop
115 #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY)
116  // do nothing.
117 #elif defined(Q_OS_INTEGRITY)
118  // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead
119  if (socketpair(AF_INET, SOCK_STREAM, 0, thread_pipe) == -1) {
120  perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair");
121  pipefail = true;
122  } else {
123  initThreadPipeFD(thread_pipe[0]);
124  initThreadPipeFD(thread_pipe[1]);
125  }
126 #elif defined(Q_OS_VXWORKS)
127  char name[20];
128  qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
129 
130  // make sure there is no pipe with this name
131  pipeDevDelete(name, true);
132  // create the pipe
133  if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
134  perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device");
135  pipefail = true;
136  } else {
137  if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) {
138  perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
139  pipefail = true;
140  } else {
141  initThreadPipeFD(thread_pipe[0]);
142  thread_pipe[1] = thread_pipe[0];
143  }
144  }
145 #else
146  if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) {
147  perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
148  pipefail = true;
149  }
150 #endif
151 
152  if (pipefail)
153  qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
154 
155  sn_highest = -1;
156 
157  interrupt = false;
158 }
159 
161 {
162 #if defined(Q_OS_NACL) || defined (Q_OS_BLACKBERRY)
163  // do nothing.
164 #elif defined(Q_OS_VXWORKS)
165  close(thread_pipe[0]);
166 
167  char name[20];
168  qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdSelf()));
169 
170  pipeDevDelete(name, true);
171 #else
172  // cleanup the common parts of the event loop
173  close(thread_pipe[0]);
174  close(thread_pipe[1]);
175 #endif
176 
177  // cleanup timers
179 }
180 
181 int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout)
182 {
184 
185  // needed in QEventDispatcherUNIX::select()
187 
188  int nsel;
189  do {
190  if (mainThread) {
191  while (signal_received) {
192  signal_received = 0;
193  for (int i = 0; i < NSIG; ++i) {
194  if (signals_fired[i]) {
195  signals_fired[i] = 0;
197  }
198  }
199  }
200  }
201 
202  // Process timers and socket notifiers - the common UNIX stuff
203  int highest = 0;
204  if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {
205  // return the highest fd we can wait for input on
209  highest = sn_highest;
210  } else {
211  FD_ZERO(&sn_vec[0].select_fds);
212  FD_ZERO(&sn_vec[1].select_fds);
213  FD_ZERO(&sn_vec[2].select_fds);
214  }
215 
216  int wakeUpFd = initThreadWakeUp();
217  highest = qMax(highest, wakeUpFd);
218 
219  nsel = q->select(highest + 1,
220  &sn_vec[0].select_fds,
221  &sn_vec[1].select_fds,
222  &sn_vec[2].select_fds,
223  timeout);
224  } while (nsel == -1 && (errno == EINTR || errno == EAGAIN));
225 
226  if (nsel == -1) {
227  if (errno == EBADF) {
228  // it seems a socket notifier has a bad fd... find out
229  // which one it is and disable it
230  fd_set fdset;
231  timeval tm;
232  tm.tv_sec = tm.tv_usec = 0l;
233 
234  for (int type = 0; type < 3; ++type) {
236  if (list.size() == 0)
237  continue;
238 
239  for (int i = 0; i < list.size(); ++i) {
240  QSockNot *sn = list[i];
241 
242  FD_ZERO(&fdset);
243  FD_SET(sn->fd, &fdset);
244 
245  int ret = -1;
246  do {
247  switch (type) {
248  case 0: // read
249  ret = select(sn->fd + 1, &fdset, 0, 0, &tm);
250  break;
251  case 1: // write
252  ret = select(sn->fd + 1, 0, &fdset, 0, &tm);
253  break;
254  case 2: // except
255  ret = select(sn->fd + 1, 0, 0, &fdset, &tm);
256  break;
257  }
258  } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
259 
260  if (ret == -1 && errno == EBADF) {
261  // disable the invalid socket notifier
262  static const char *t[] = { "Read", "Write", "Exception" };
263  qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
264  sn->fd, t[type]);
265  sn->obj->setEnabled(false);
266  }
267  }
268  }
269  } else {
270  // EINVAL... shouldn't happen, so let's complain to stderr
271  // and hope someone sends us a bug report
272  perror("select");
273  }
274  }
275 
276  int nevents = processThreadWakeUp(nsel);
277 
278  // activate socket notifiers
279  if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) {
280  // if select says data is ready on any socket, then set the socket notifier
281  // to pending
282  for (int i=0; i<3; i++) {
283  QSockNotType::List &list = sn_vec[i].list;
284  for (int j = 0; j < list.size(); ++j) {
285  QSockNot *sn = list[j];
286  if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))
287  q->setSocketNotifierPending(sn->obj);
288  }
289  }
290  }
291  return (nevents + q->activateSocketNotifiers());
292 }
293 
295 {
296  FD_SET(thread_pipe[0], &sn_vec[0].select_fds);
297  return thread_pipe[0];
298 }
299 
301 {
302  if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) {
303  // some other thread woke us up... consume the data on the thread pipe so that
304  // select doesn't immediately return next time
305 #if defined(Q_OS_VXWORKS)
306  char c[16];
307  ::read(thread_pipe[0], c, sizeof(c));
308  ::ioctl(thread_pipe[0], FIOFLUSH, 0);
309 #else
310  char c[16];
311  while (::read(thread_pipe[0], c, sizeof(c)) > 0)
312  ;
313 #endif
314  if (!wakeUps.testAndSetRelease(1, 0)) {
315  // hopefully, this is dead code
316  qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
317  }
318  return 1;
319  }
320  return 0;
321 }
322 
323 /*
324  * Internal functions for manipulating timer data structures. The
325  * timerBitVec array is used for keeping track of timer identifiers.
326  */
327 
329 {
330 #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL)
332  // not using monotonic timers, initialize the timeChanged() machinery
333  previousTime = qt_gettime();
334 
335  tms unused;
336  previousTicks = times(&unused);
337 
338  ticksPerSecond = sysconf(_SC_CLK_TCK);
339  msPerTick = 1000/ticksPerSecond;
340  } else {
341  // detected monotonic timers
342  previousTime.tv_sec = previousTime.tv_usec = 0;
343  previousTicks = 0;
344  ticksPerSecond = 0;
345  msPerTick = 0;
346  }
347 #endif
348 
349  firstTimerInfo = 0;
350 }
351 
353 {
354  return (currentTime = qt_gettime());
355 }
356 
357 #if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
358 
359 timeval qAbsTimeval(const timeval &t)
360 {
361  timeval tmp = t;
362  if (tmp.tv_sec < 0) {
363  tmp.tv_sec = -tmp.tv_sec - 1;
364  tmp.tv_usec -= 1000000;
365  }
366  if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
367  tmp.tv_usec = -tmp.tv_usec;
368  }
369  return normalizedTimeval(tmp);
370 }
371 
372 /*
373  Returns true if the real time clock has changed by more than 10%
374  relative to the processor time since the last time this function was
375  called. This presumably means that the system time has been changed.
376 
377  If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.
378 */
379 bool QTimerInfoList::timeChanged(timeval *delta)
380 {
381 #ifdef Q_OS_NACL
382  Q_UNUSED(delta)
383  return false; // Calling "times" crashes.
384 #endif
385  struct tms unused;
386  clock_t currentTicks = times(&unused);
387 
388  clock_t elapsedTicks = currentTicks - previousTicks;
389  timeval elapsedTime = currentTime - previousTime;
390 
391  timeval elapsedTimeTicks;
392  elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
393  elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
394 
395  timeval dummy;
396  if (!delta)
397  delta = &dummy;
398  *delta = elapsedTime - elapsedTimeTicks;
399 
400  previousTicks = currentTicks;
401  previousTime = currentTime;
402 
403  // If tick drift is more than 10% off compared to realtime, we assume that the clock has
404  // been set. Of course, we have to allow for the tick granularity as well.
405  timeval tickGranularity;
406  tickGranularity.tv_sec = 0;
407  tickGranularity.tv_usec = msPerTick * 1000;
408  return elapsedTimeTicks < ((qAbsTimeval(*delta) - tickGranularity) * 10);
409 }
410 
412 {
414  return;
415  timeval delta;
416  if (timeChanged(&delta))
417  timerRepair(delta);
418 }
419 
420 #else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
421 
423 {
424 }
425 
426 #endif
427 
428 /*
429  insert timer info into list
430 */
432 {
433  int index = size();
434  while (index--) {
435  register const QTimerInfo * const t = at(index);
436  if (!(ti->timeout < t->timeout))
437  break;
438  }
439  insert(index+1, ti);
440 }
441 
442 /*
443  repair broken timer
444 */
445 void QTimerInfoList::timerRepair(const timeval &diff)
446 {
447  // repair all timers
448  for (int i = 0; i < size(); ++i) {
449  register QTimerInfo *t = at(i);
450  t->timeout = t->timeout + diff;
451  }
452 }
453 
454 /*
455  Returns the time to wait for the next timer, or null if no timers
456  are waiting.
457 */
459 {
460  timeval currentTime = updateCurrentTime();
461  repairTimersIfNeeded();
462 
463  // Find first waiting timer not already active
464  QTimerInfo *t = 0;
465  for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
466  if (!(*it)->activateRef) {
467  t = *it;
468  break;
469  }
470  }
471 
472  if (!t)
473  return false;
474 
475  if (currentTime < t->timeout) {
476  // time to wait
477  tm = t->timeout - currentTime;
478  } else {
479  // no time to wait
480  tm.tv_sec = 0;
481  tm.tv_usec = 0;
482  }
483 
484  return true;
485 }
486 
487 void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object)
488 {
489  QTimerInfo *t = new QTimerInfo;
490  t->id = timerId;
491  t->interval.tv_sec = interval / 1000;
492  t->interval.tv_usec = (interval % 1000) * 1000;
493  t->timeout = updateCurrentTime() + t->interval;
494  t->obj = object;
495  t->activateRef = 0;
496 
497  timerInsert(t);
498 }
499 
501 {
502  // set timer inactive
503  for (int i = 0; i < count(); ++i) {
504  register QTimerInfo *t = at(i);
505  if (t->id == timerId) {
506  // found it
507  removeAt(i);
508  if (t == firstTimerInfo)
509  firstTimerInfo = 0;
510  if (t->activateRef)
511  *(t->activateRef) = 0;
512 
513  // release the timer id
516 
517  delete t;
518  return true;
519  }
520  }
521  // id not found
522  return false;
523 }
524 
526 {
527  if (isEmpty())
528  return false;
529  for (int i = 0; i < count(); ++i) {
530  register QTimerInfo *t = at(i);
531  if (t->obj == object) {
532  // object found
533  removeAt(i);
534  if (t == firstTimerInfo)
535  firstTimerInfo = 0;
536  if (t->activateRef)
537  *(t->activateRef) = 0;
538 
539  // release the timer id
542 
543  delete t;
544  // move back one so that we don't skip the new current item
545  --i;
546  }
547  }
548  return true;
549 }
550 
552 {
553  QList<QPair<int, int> > list;
554  for (int i = 0; i < count(); ++i) {
555  register const QTimerInfo * const t = at(i);
556  if (t->obj == object)
557  list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000);
558  }
559  return list;
560 }
561 
562 /*
563  Activate pending timers, returning how many where activated.
564 */
566 {
568  return 0; // nothing to do
569 
570  int n_act = 0, maxCount = 0;
571  firstTimerInfo = 0;
572 
573  timeval currentTime = updateCurrentTime();
574  repairTimersIfNeeded();
575 
576 
577  // Find out how many timer have expired
578  for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
579  if (currentTime < (*it)->timeout)
580  break;
581  maxCount++;
582  }
583 
584  //fire the timers.
585  while (maxCount--) {
586  if (isEmpty())
587  break;
588 
589  QTimerInfo *currentTimerInfo = first();
590  if (currentTime < currentTimerInfo->timeout)
591  break; // no timer has expired
592 
593  if (!firstTimerInfo) {
594  firstTimerInfo = currentTimerInfo;
595  } else if (firstTimerInfo == currentTimerInfo) {
596  // avoid sending the same timer multiple times
597  break;
598  } else if (currentTimerInfo->interval < firstTimerInfo->interval
599  || currentTimerInfo->interval == firstTimerInfo->interval) {
600  firstTimerInfo = currentTimerInfo;
601  }
602 
603  // remove from list
604  removeFirst();
605 
606  // determine next timeout time
607  currentTimerInfo->timeout += currentTimerInfo->interval;
608  if (currentTimerInfo->timeout < currentTime)
609  currentTimerInfo->timeout = currentTime + currentTimerInfo->interval;
610 
611  // reinsert timer
612  timerInsert(currentTimerInfo);
613  if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0)
614  n_act++;
615 
616  if (!currentTimerInfo->activateRef) {
617  // send event, but don't allow it to recurse
618  currentTimerInfo->activateRef = &currentTimerInfo;
619 
620  QTimerEvent e(currentTimerInfo->id);
621  QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
622 
623  if (currentTimerInfo)
624  currentTimerInfo->activateRef = 0;
625  }
626  }
627 
628  firstTimerInfo = 0;
629  return n_act;
630 }
631 
634 { }
635 
637  : QAbstractEventDispatcher(dd, parent)
638 { }
639 
641 {
643  d->threadData->eventDispatcher = 0;
644 }
645 
646 int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
647  timeval *timeout)
648 {
649  return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);
650 }
651 
655 void QEventDispatcherUNIX::registerTimer(int timerId, int interval, QObject *obj)
656 {
657 #ifndef QT_NO_DEBUG
658  if (timerId < 1 || interval < 0 || !obj) {
659  qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments");
660  return;
661  } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
662  qWarning("QObject::startTimer: timers cannot be started from another thread");
663  return;
664  }
665 #endif
666 
668  d->timerList.registerTimer(timerId, interval, obj);
669 }
670 
675 {
676 #ifndef QT_NO_DEBUG
677  if (timerId < 1) {
678  qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument");
679  return false;
680  } else if (thread() != QThread::currentThread()) {
681  qWarning("QObject::killTimer: timers cannot be stopped from another thread");
682  return false;
683  }
684 #endif
685 
687  return d->timerList.unregisterTimer(timerId);
688 }
689 
694 {
695 #ifndef QT_NO_DEBUG
696  if (!object) {
697  qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument");
698  return false;
699  } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
700  qWarning("QObject::killTimers: timers cannot be stopped from another thread");
701  return false;
702  }
703 #endif
704 
706  return d->timerList.unregisterTimers(object);
707 }
708 
711 {
712  if (!object) {
713  qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
714  return QList<TimerInfo>();
715  }
716 
717  Q_D(const QEventDispatcherUNIX);
718  return d->timerList.registeredTimers(object);
719 }
720 
721 /*****************************************************************************
722  Socket notifier type
723  *****************************************************************************/
725 {
726  FD_ZERO(&select_fds);
727  FD_ZERO(&enabled_fds);
728  FD_ZERO(&pending_fds);
729 }
730 
732 {
733  for (int i = 0; i < list.size(); ++i)
734  delete list[i];
735 }
736 
737 /*****************************************************************************
738  QEventDispatcher implementations for UNIX
739  *****************************************************************************/
740 
742 {
743  Q_ASSERT(notifier);
744  int sockfd = notifier->socket();
745  int type = notifier->type();
746 #ifndef QT_NO_DEBUG
747  if (sockfd < 0
748  || unsigned(sockfd) >= FD_SETSIZE) {
749  qWarning("QSocketNotifier: Internal error");
750  return;
751  } else if (notifier->thread() != thread()
752  || thread() != QThread::currentThread()) {
753  qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
754  return;
755  }
756 #endif
757 
759  QSockNotType::List &list = d->sn_vec[type].list;
760  fd_set *fds = &d->sn_vec[type].enabled_fds;
761  QSockNot *sn;
762 
763  sn = new QSockNot;
764  sn->obj = notifier;
765  sn->fd = sockfd;
766  sn->queue = &d->sn_vec[type].pending_fds;
767 
768  int i;
769  for (i = 0; i < list.size(); ++i) {
770  QSockNot *p = list[i];
771  if (p->fd < sockfd)
772  break;
773  if (p->fd == sockfd) {
774  static const char *t[] = { "Read", "Write", "Exception" };
775  qWarning("QSocketNotifier: Multiple socket notifiers for "
776  "same socket %d and type %s", sockfd, t[type]);
777  }
778  }
779  list.insert(i, sn);
780 
781  FD_SET(sockfd, fds);
782  d->sn_highest = qMax(d->sn_highest, sockfd);
783 }
784 
786 {
787  Q_ASSERT(notifier);
788  int sockfd = notifier->socket();
789  int type = notifier->type();
790 #ifndef QT_NO_DEBUG
791  if (sockfd < 0
792  || unsigned(sockfd) >= FD_SETSIZE) {
793  qWarning("QSocketNotifier: Internal error");
794  return;
795  } else if (notifier->thread() != thread()
796  || thread() != QThread::currentThread()) {
797  qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
798  return;
799  }
800 #endif
801 
803  QSockNotType::List &list = d->sn_vec[type].list;
804  fd_set *fds = &d->sn_vec[type].enabled_fds;
805  QSockNot *sn = 0;
806  int i;
807  for (i = 0; i < list.size(); ++i) {
808  sn = list[i];
809  if(sn->obj == notifier && sn->fd == sockfd)
810  break;
811  }
812  if (i == list.size()) // not found
813  return;
814 
815  FD_CLR(sockfd, fds); // clear fd bit
816  FD_CLR(sockfd, sn->queue);
817  d->sn_pending_list.removeAll(sn); // remove from activation list
818  list.removeAt(i); // remove notifier found above
819  delete sn;
820 
821  if (d->sn_highest == sockfd) { // find highest fd
822  d->sn_highest = -1;
823  for (int i=0; i<3; i++) {
824  if (!d->sn_vec[i].list.isEmpty())
825  d->sn_highest = qMax(d->sn_highest, // list is fd-sorted
826  d->sn_vec[i].list[0]->fd);
827  }
828  }
829 }
830 
832 {
833  Q_ASSERT(notifier);
834  int sockfd = notifier->socket();
835  int type = notifier->type();
836 #ifndef QT_NO_DEBUG
837  if (sockfd < 0
838  || unsigned(sockfd) >= FD_SETSIZE) {
839  qWarning("QSocketNotifier: Internal error");
840  return;
841  }
842  Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread());
843 #endif
844 
846  QSockNotType::List &list = d->sn_vec[type].list;
847  QSockNot *sn = 0;
848  int i;
849  for (i = 0; i < list.size(); ++i) {
850  sn = list[i];
851  if(sn->obj == notifier && sn->fd == sockfd)
852  break;
853  }
854  if (i == list.size()) // not found
855  return;
856 
857  // We choose a random activation order to be more fair under high load.
858  // If a constant order is used and a peer early in the list can
859  // saturate the IO, it might grab our attention completely.
860  // Also, if we're using a straight list, the callback routines may
861  // delete other entries from the list before those other entries are
862  // processed.
863  if (! FD_ISSET(sn->fd, sn->queue)) {
864  if (d->sn_pending_list.isEmpty()) {
865  d->sn_pending_list.append(sn);
866  } else {
867  d->sn_pending_list.insert((qrand() & 0xff) %
868  (d->sn_pending_list.size()+1), sn);
869  }
870  FD_SET(sn->fd, sn->queue);
871  }
872 }
873 
875 {
878  return d->timerList.activateTimers();
879 }
880 
882 {
884  if (d->sn_pending_list.isEmpty())
885  return 0;
886 
887  // activate entries
888  int n_act = 0;
890  while (!d->sn_pending_list.isEmpty()) {
891  QSockNot *sn = d->sn_pending_list.takeFirst();
892  if (FD_ISSET(sn->fd, sn->queue)) {
893  FD_CLR(sn->fd, sn->queue);
894  QCoreApplication::sendEvent(sn->obj, &event);
895  ++n_act;
896  }
897  }
898  return n_act;
899 }
900 
901 bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
902 {
904  d->interrupt = false;
905 
906  // we are awake, broadcast it
907  emit awake();
908  QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
909 
910  int nevents = 0;
911  const bool canWait = (d->threadData->canWaitLocked()
912  && !d->interrupt
913  && (flags & QEventLoop::WaitForMoreEvents));
914 
915  if (canWait)
916  emit aboutToBlock();
917 
918  if (!d->interrupt) {
919  // return the maximum time we can wait for an event.
920  timeval *tm = 0;
921  timeval wait_tm = { 0l, 0l };
922  if (!(flags & QEventLoop::X11ExcludeTimers)) {
923  if (d->timerList.timerWait(wait_tm))
924  tm = &wait_tm;
925  }
926 
927  if (!canWait) {
928  if (!tm)
929  tm = &wait_tm;
930 
931  // no time to wait
932  tm->tv_sec = 0l;
933  tm->tv_usec = 0l;
934  }
935 
936  nevents = d->doSelect(flags, tm);
937 
938  // activate timers
939  if (! (flags & QEventLoop::X11ExcludeTimers)) {
940  nevents += activateTimers();
941  }
942  }
943  // return true if we handled events, false otherwise
944  return (nevents > 0);
945 }
946 
948 {
949  extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
950  return qGlobalPostedEventsCount();
951 }
952 
954 {
956  if (d->wakeUps.testAndSetAcquire(0, 1)) {
957  char c = 0;
958  qt_safe_write( d->thread_pipe[1], &c, 1 );
959  }
960 }
961 
963 {
965  d->interrupt = true;
966  wakeUp();
967 }
968 
970 { }
971 
972 
973 
974 
975 void QCoreApplication::watchUnixSignal(int sig, bool watch)
976 {
977  if (sig < NSIG) {
978  struct sigaction sa;
979  sigemptyset(&(sa.sa_mask));
980  sa.sa_flags = 0;
981  if (watch)
982  sa.sa_handler = signalHandler;
983  else
984  sa.sa_handler = SIG_DFL;
985  sigaction(sig, &sa, 0);
986  }
987 }
988 
static sig_atomic_t signal_received
double d
Definition: qnumeric_p.h:62
QSocketNotifier * obj
bool unregisterTimer(int timerId)
static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data)
void setSocketNotifierPending(QSocketNotifier *notifier)
int type
Definition: qmetatype.cpp:239
unsigned char c[8]
Definition: qnumeric_p.h:62
void flush()
Flushes the event queue.
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QList< TimerInfo > registeredTimers(QObject *object) const
Returns a list of registered timers for object.
#define it(className, varName)
int doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout)
void timerInsert(QTimerInfo *)
bool hasPendingEvents()
Returns true if there is an event waiting; otherwise returns false.
#define at(className, varName)
int select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
void registerTimer(int timerId, int interval, QObject *object)
Q_CORE_EXPORT int qsnprintf(char *str, size_t n, const char *fmt,...)
Q_CORE_EXPORT int qrand()
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
virtual bool event(QEvent *)
This virtual function receives events to an object and should return true if the event e was recogniz...
Definition: qobject.cpp:1200
#define Q_D(Class)
Definition: qglobal.h:2482
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:177
void unixSignal(int)
This signal is emitted whenever a Unix signal is received by the application.
static bool isMonotonic()
Returns true if this is a monotonic clock, false otherwise.
bool testAndSetRelease(int expectedValue, int newValue)
Atomic test-and-set.
Type type() const
Returns the socket event type specified to the constructor.
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
void registerSocketNotifier(QSocketNotifier *notifier)
Registers notifier with the event loop.
#define Q_Q(Class)
Definition: qglobal.h:2483
Q_CORE_EXPORT bool qt_disable_lowpriority_timers
void timerRepair(const timeval &)
friend class const_iterator
Definition: qlist.h:264
QTimerInfo ** activateRef
static QThread * currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
Definition: qthread.cpp:419
QList< QPair< int, int > > registeredTimers(QObject *object) const
bool unregisterTimer(int timerId)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void awake()
This signal is emitted after the event loop returns from a function that could block.
static bool isEmpty(const char *str)
static sig_atomic_t signals_fired[NSIG]
static void watchUnixSignal(int signal, bool watch)
timeval & normalizedTimeval(timeval &t)
Definition: qcore_unix_p.h:104
const char * name
bool unregisterTimers(QObject *object)
#define emit
Definition: qobjectdefs.h:76
void * unused
Definition: qobject_p.h:208
Q_CORE_EXPORT void qWarning(const char *,...)
uint inThreadChangeEvent
Definition: qobject.h:103
unsigned int uint
Definition: qglobal.h:996
static Bigint * diff(Bigint *a, Bigint *b)
static int qt_safe_pipe(int pipefd[2], int flags=0)
Definition: qcore_unix_p.h:191
static bool sendEvent(QObject *receiver, QEvent *event)
Sends event event directly to receiver receiver, using the notify() function.
void * HANDLE
Definition: qnamespace.h:1671
Q_CORE_EXPORT uint qGlobalPostedEventsCount()
void interrupt()
Interrupts event dispatching; i.
void wakeUp()
Wakes up the event loop.
Q_CORE_EXPORT void qFatal(const char *,...)
int fcntl(int, int,...)
void aboutToBlock()
This signal is emitted before the event loop calls a function that could block.
bool unregisterTimers(QObject *object)
int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, const struct timeval *orig_timeout)
Definition: qcore_unix.cpp:73
#define Q_CORE_EXPORT
Definition: qglobal.h:1449
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:341
static QCoreApplication * instance()
Returns a pointer to the application&#39;s QCoreApplication (or QApplication) instance.
int sigaction(int, const struct sigaction *, struct sigaction *)
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
void insert(int idx, const T &t)
Definition: qpodlist_p.h:76
bool processEvents(QEventLoop::ProcessEventsFlags flags)
Processes pending events that match flags until there are no more events to process.
void removeAt(int idx)
Definition: qpodlist_p.h:95
void setEnabled(bool)
If enable is true, the notifier is enabled; otherwise the notifier is disabled.
QFactoryLoader * l
virtual int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timeval *timeout)
quint16 index
QObject * parent
Definition: qobject.h:92
void registerTimer(int timerId, int interval, QObject *object)
bool timerWait(timeval &)
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
virtual int processThreadWakeUp(int nsel)
QEventDispatcherUNIX(QObject *parent=0)
The QEvent class is the base class of all event classes.
Definition: qcoreevent.h:56
static void signalHandler(int sig)
timeval qt_gettime()
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
#define O_RDWR
void unregisterSocketNotifier(QSocketNotifier *notifier)
Unregisters notifier from the event dispatcher.
The QAbstractEventDispatcher class provides an interface to manage Qt&#39;s event queue.
Qt::HANDLE qt_application_thread_id
int open(const char *, int,...)
static qint64 qt_safe_write(int fd, const void *data, qint64 len)
Definition: qcore_unix_p.h:282
int size() const
int errno
int socket() const
Returns the socket identifier specified to the constructor.
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
static Qt::HANDLE currentThreadId()
Returns the thread handle of the currently executing thread.