summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qcore_unix.cpp
diff options
context:
space:
mode:
authorLouai Al-Khanji <louai.al-khanji@theqtcompany.com>2015-12-02 17:22:32 -0800
committerLouai Al-Khanji <louai.al-khanji@theqtcompany.com>2015-12-05 00:47:36 +0000
commitf0a6d45cc8ca0b17838046c1c17efbc64773f2b5 (patch)
tree5ce13632dc05400b4c61ff817b01322111abde24 /src/corelib/kernel/qcore_unix.cpp
parentc456fb366a92cd08f6d2bf95b6974fea82340003 (diff)
qt_poll: split out into separate file and sanitize build
The qt_poll function calls recv to query whether fds marked by select as readable should be marked POLLIN or POLLHUP in the pollfd structure. On many platforms such as QNX this requires extra link-time libraries which were not previously required by QtCore. While the qt_poll function is intended as a fallback mechanism only for those platforms which do not implement poll natively, the function was compiled unconditionally whenever QT_BUILD_INTERNAL was defined, e.g. in developer builds. Additionally the function was included on those systems that define poll in system headers so that configure determines build-time availability, but do not define _POSIX_POLL > 0 or indicate POSIX:2008 compliance via either the _POSIX_VERSION or _XOPEN_VERSION macros. On those systems a sysconf query for _SC_POLL was performed to determine at runtime whether to call the system poll or qt_poll. Both of these cases are in fact counterproductive. In the first case the sole consumer of the function is a single manual unit test. In the second, to my knowledge no platform requires the runtime fallback. Despite that, we were forcing an extra dylib in both cases. Both cases are fixed by 1) moving the implementation into its own file for the unit test to include and 2) dropping the dynamic fallback if configure determines availability of poll at compile-time. This also reverts commit 13777097118c496391d4b9656b95097ac25e4a40, which added -lsocket for QtCore on QNX. Change-Id: I2dd10695c5d4cac81b68d2c2558797f3cdabc153 Reviewed-by: James McDonnell <jmcdonnell@qnx.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/kernel/qcore_unix.cpp')
-rw-r--r--src/corelib/kernel/qcore_unix.cpp220
1 files changed, 5 insertions, 215 deletions
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index bb75823bff..97c0efc36f 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -57,28 +57,6 @@ QT_BEGIN_NAMESPACE
# define QT_HAVE_PPOLL
#endif
-#ifndef _POSIX_POLL
-# if defined(QT_HAVE_PPOLL) || _POSIX_VERSION >= 200809L || _XOPEN_VERSION >= 700
-# define _POSIX_POLL 1
-# elif defined(QT_HAVE_POLL)
-# define _POSIX_POLL 0
-# else
-# define _POSIX_POLL -1
-# endif
-#endif
-
-#if defined(Q_OS_QNX) || _POSIX_POLL <= 0 || defined(QT_BUILD_INTERNAL)
-static inline struct timeval timespecToTimeval(const struct timespec &ts)
-{
- struct timeval tv;
-
- tv.tv_sec = ts.tv_sec;
- tv.tv_usec = ts.tv_nsec / 1000;
-
- return tv;
-}
-#endif
-
static inline bool time_update(struct timespec *tv, const struct timespec &start,
const struct timespec &timeout)
{
@@ -142,193 +120,7 @@ int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
return qt_safe_select(nfds, fdread, fdwrite, 0, &tv);
}
-#if _POSIX_POLL <= 0 || defined(QT_BUILD_INTERNAL)
-
-#define QT_POLL_READ_MASK (POLLIN | POLLRDNORM)
-#define QT_POLL_WRITE_MASK (POLLOUT | POLLWRNORM | POLLWRBAND)
-#define QT_POLL_EXCEPT_MASK (POLLPRI | POLLRDBAND)
-#define QT_POLL_ERROR_MASK (POLLERR | POLLNVAL)
-#define QT_POLL_EVENTS_MASK (QT_POLL_READ_MASK | QT_POLL_WRITE_MASK | QT_POLL_EXCEPT_MASK)
-
-static inline int qt_poll_prepare(struct pollfd *fds, nfds_t nfds,
- fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
-{
- int max_fd = -1;
-
- FD_ZERO(read_fds);
- FD_ZERO(write_fds);
- FD_ZERO(except_fds);
-
- for (nfds_t i = 0; i < nfds; i++) {
- if (fds[i].fd >= FD_SETSIZE) {
- errno = EINVAL;
- return -1;
- }
-
- if ((fds[i].fd < 0) || (fds[i].revents & QT_POLL_ERROR_MASK))
- continue;
-
- if (fds[i].events & QT_POLL_READ_MASK)
- FD_SET(fds[i].fd, read_fds);
-
- if (fds[i].events & QT_POLL_WRITE_MASK)
- FD_SET(fds[i].fd, write_fds);
-
- if (fds[i].events & QT_POLL_EXCEPT_MASK)
- FD_SET(fds[i].fd, except_fds);
-
- if (fds[i].events & QT_POLL_EVENTS_MASK)
- max_fd = qMax(max_fd, fds[i].fd);
- }
-
- return max_fd + 1;
-}
-
-static inline void qt_poll_examine_ready_read(struct pollfd &pfd)
-{
- int res;
- char data;
-
- EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK));
- const int error = (res < 0) ? errno : 0;
-
- if (res == 0) {
- pfd.revents |= POLLHUP;
- } else if (res > 0 || error == ENOTSOCK || error == ENOTCONN) {
- pfd.revents |= QT_POLL_READ_MASK & pfd.events;
- } else {
- switch (error) {
- case ESHUTDOWN:
- case ECONNRESET:
- case ECONNABORTED:
- case ENETRESET:
- pfd.revents |= POLLHUP;
- break;
- default:
- pfd.revents |= POLLERR;
- break;
- }
- }
-}
-
-static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds,
- fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
-{
- int result = 0;
-
- for (nfds_t i = 0; i < nfds; i++) {
- if (fds[i].fd < 0)
- continue;
-
- if (FD_ISSET(fds[i].fd, read_fds))
- qt_poll_examine_ready_read(fds[i]);
-
- if (FD_ISSET(fds[i].fd, write_fds))
- fds[i].revents |= QT_POLL_WRITE_MASK & fds[i].events;
-
- if (FD_ISSET(fds[i].fd, except_fds))
- fds[i].revents |= QT_POLL_EXCEPT_MASK & fds[i].events;
-
- if (fds[i].revents != 0)
- result++;
- }
-
- return result;
-}
-
-static inline bool qt_poll_is_bad_fd(int fd)
-{
- int ret;
- EINTR_LOOP(ret, fcntl(fd, F_GETFD));
- return (ret == -1 && errno == EBADF);
-}
-
-static inline int qt_poll_mark_bad_fds(struct pollfd *fds, const nfds_t nfds)
-{
- int n_marked = 0;
-
- for (nfds_t i = 0; i < nfds; i++) {
- if (fds[i].fd < 0)
- continue;
-
- if (fds[i].revents & QT_POLL_ERROR_MASK)
- continue;
-
- if (qt_poll_is_bad_fd(fds[i].fd)) {
- fds[i].revents |= POLLNVAL;
- n_marked++;
- }
- }
-
- return n_marked;
-}
-
-Q_AUTOTEST_EXPORT int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
-{
- if (!fds && nfds) {
- errno = EFAULT;
- return -1;
- }
-
- fd_set read_fds, write_fds, except_fds;
- struct timeval tv, *ptv = 0;
-
- if (timeout_ts) {
- tv = timespecToTimeval(*timeout_ts);
- ptv = &tv;
- }
-
- int n_bad_fds = 0;
-
- for (nfds_t i = 0; i < nfds; i++) {
- fds[i].revents = 0;
-
- if (fds[i].fd < 0)
- continue;
-
- if (fds[i].events & QT_POLL_EVENTS_MASK)
- continue;
-
- if (qt_poll_is_bad_fd(fds[i].fd)) {
- // Mark bad file descriptors that have no event flags set
- // here, as we won't be passing them to select below and therefore
- // need to do the check ourselves
- fds[i].revents = POLLNVAL;
- n_bad_fds++;
- }
- }
-
- forever {
- const int max_fd = qt_poll_prepare(fds, nfds, &read_fds, &write_fds, &except_fds);
-
- if (max_fd < 0)
- return max_fd;
-
- if (n_bad_fds > 0) {
- tv.tv_sec = 0;
- tv.tv_usec = 0;
- ptv = &tv;
- }
-
- const int ret = ::select(max_fd, &read_fds, &write_fds, &except_fds, ptv);
-
- if (ret == 0)
- return n_bad_fds;
-
- if (ret > 0)
- return qt_poll_sweep(fds, nfds, &read_fds, &write_fds, &except_fds);
-
- if (errno != EBADF)
- return -1;
-
- // We have at least one bad file descriptor that we waited on, find out which and try again
- n_bad_fds += qt_poll_mark_bad_fds(fds, nfds);
- }
-}
-
-#endif // _POSIX_POLL <= 0 || defined(QT_BUILD_INTERNAL)
-
-#if !defined(QT_HAVE_PPOLL) && ((_POSIX_POLL > 0) || defined(_SC_POLL))
+#if !defined(QT_HAVE_PPOLL) && defined(QT_HAVE_POLL)
static inline int timespecToMillisecs(const struct timespec *ts)
{
return (ts == NULL) ? -1 :
@@ -336,18 +128,16 @@ static inline int timespecToMillisecs(const struct timespec *ts)
}
#endif
+// defined in qpoll.cpp
+int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
+
static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
{
#if defined(QT_HAVE_PPOLL)
return ::ppoll(fds, nfds, timeout_ts, Q_NULLPTR);
-#elif _POSIX_POLL > 0
+#elif defined(QT_HAVE_POLL)
return ::poll(fds, nfds, timespecToMillisecs(timeout_ts));
#else
-# if defined(_SC_POLL)
- static const bool have_poll = (sysconf(_SC_POLL) > 0);
- if (have_poll)
- return ::poll(fds, nfds, timespecToMillisecs(timeout_ts));
-# endif
return qt_poll(fds, nfds, timeout_ts);
#endif
}