From 2d44415b27247db9dea221b4c56b88611984b21b Mon Sep 17 00:00:00 2001 From: Than Ngo Date: May 08 2013 14:00:19 +0000 Subject: add polll support --- diff --git a/qt5-poll.patch b/qt5-poll.patch new file mode 100644 index 0000000..c8c4d69 --- /dev/null +++ b/qt5-poll.patch @@ -0,0 +1,735 @@ +commit 8a2d9073e959356808ce1685822b839d880e6498 +Author: Florian Weimer +Date: Fri Sep 14 17:27:35 2012 +0200 + + Replace most calls to select(2) with poll(2) + + select(2) limits the number of file descriptor in a process to + FD_SETSIZE (typically 1023). Process creation and certain socket + operations fail because they call select(2) on a file descriptor outside + the FD_SETSIZE range. + + The remaining select(2) calls are used for timeouts only, or are in the + traditional event loop. The glib-based event loop does not use + select(2), so this should be sufficient. + + This change adds a poll emulation for VxWorks, which only offers + select(2). + + Change-Id: I9b0cf5bec81da70b29c501c62d14fb57df87fa61 + +diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp +index e159bf8..bb8a3ae 100644 +--- a/src/corelib/io/qprocess_unix.cpp ++++ b/src/corelib/io/qprocess_unix.cpp +@@ -134,13 +134,6 @@ static void qt_sa_sigchld_handler(int signum) + oldAction(signum); + } + +-static inline void add_fd(int &nfds, int fd, fd_set *fdset) +-{ +- FD_SET(fd, fdset); +- if ((fd) > nfds) +- nfds = fd; +-} +- + struct QProcessInfo { + QProcess *process; + int deathPipe; +@@ -235,9 +228,9 @@ QProcessManager::~QProcessManager() + void QProcessManager::run() + { + forever { +- fd_set readset; +- FD_ZERO(&readset); +- FD_SET(qt_qprocess_deadChild_pipe[0], &readset); ++ pollfd fd; ++ fd.fd = qt_qprocess_deadChild_pipe[0]; ++ fd.events = POLLIN; + + #if defined (QPROCESS_DEBUG) + qDebug() << "QProcessManager::run() waiting for children to die"; +@@ -246,8 +239,8 @@ void QProcessManager::run() + // block forever, or until activity is detected on the dead child + // pipe. the only other peers are the SIGCHLD signal handler, and the + // QProcessManager destructor. +- int nselect = select(qt_qprocess_deadChild_pipe[0] + 1, &readset, 0, 0, 0); +- if (nselect < 0) { ++ int ret = qt_safe_poll(&fd, 1, -1, /* retry_eintr */ false); ++ if (ret < 0) { + if (errno == EINTR) + continue; + break; +@@ -996,17 +989,6 @@ void QProcessPrivate::killProcess() + ::kill(pid_t(pid), SIGKILL); + } + +-static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) +-{ +- if (timeout < 0) +- return qt_safe_select(nfds, fdread, fdwrite, 0, 0); +- +- struct timeval tv; +- tv.tv_sec = timeout / 1000; +- tv.tv_usec = (timeout % 1000) * 1000; +- return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); +-} +- + /* + Returns the difference between msecs and elapsed. If msecs is -1, + however, -1 is returned. +@@ -1029,10 +1011,10 @@ bool QProcessPrivate::waitForStarted(int msecs) + childStartedPipe[0]); + #endif + +- fd_set fds; +- FD_ZERO(&fds); +- FD_SET(childStartedPipe[0], &fds); +- if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { ++ pollfd fd; ++ fd.fd = childStartedPipe[0]; ++ fd.events = POLLIN; ++ if (qt_safe_poll(&fd, 1, msecs) == 0) { + processError = QProcess::Timedout; + q->setErrorString(QProcess::tr("Process operation timed out")); + #if defined (QPROCESS_DEBUG) +@@ -1048,6 +1030,47 @@ bool QProcessPrivate::waitForStarted(int msecs) + return startedEmitted; + } + ++class QProcessFDSet { ++ pollfd fds[5]; ++ ++ static size_t size() ++ { ++ return sizeof(fds)/sizeof(fds[0]); ++ } ++ ++public: ++ QProcessFDSet(QProcessPrivate &proc) ++ { ++ for (size_t i = 0; i < size(); ++i) { ++ fds[i].fd = -1; ++ fds[i].events = POLLIN; ++ } ++ death().fd = proc.deathPipe[0]; ++ ++ if (proc.processState == QProcess::Starting) ++ started().fd = proc.childStartedPipe[0]; ++ ++ stdout().fd = proc.stdoutChannel.pipe[0]; ++ stderr().fd = proc.stderrChannel.pipe[0]; ++ ++ if (!proc.writeBuffer.isEmpty()) { ++ stdin().fd = proc.stdinChannel.pipe[1]; ++ stdin().events = POLLOUT; ++ } ++ } ++ ++ int poll(int timeout) ++ { ++ return qt_safe_poll(fds, size(), timeout); ++ } ++ ++ pollfd &death() { return fds[0]; } ++ pollfd &started() { return fds[1]; } ++ pollfd &stdout() { return fds[2]; } ++ pollfd &stderr() { return fds[3]; } ++ pollfd &stdin() { return fds[4]; } ++}; ++ + bool QProcessPrivate::waitForReadyRead(int msecs) + { + Q_Q(QProcess); +@@ -1059,28 +1082,9 @@ bool QProcessPrivate::waitForReadyRead(int msecs) + stopWatch.start(); + + forever { +- fd_set fdread; +- fd_set fdwrite; +- +- FD_ZERO(&fdread); +- FD_ZERO(&fdwrite); +- +- int nfds = deathPipe[0]; +- FD_SET(deathPipe[0], &fdread); +- +- if (processState == QProcess::Starting) +- add_fd(nfds, childStartedPipe[0], &fdread); +- +- if (stdoutChannel.pipe[0] != -1) +- add_fd(nfds, stdoutChannel.pipe[0], &fdread); +- if (stderrChannel.pipe[0] != -1) +- add_fd(nfds, stderrChannel.pipe[0], &fdread); +- +- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) +- add_fd(nfds, stdinChannel.pipe[1], &fdwrite); +- ++ QProcessFDSet fdset(*this); + int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); +- int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); ++ int ret = fdset.poll(timeout); + if (ret < 0) { + break; + } +@@ -1090,18 +1094,18 @@ bool QProcessPrivate::waitForReadyRead(int msecs) + return false; + } + +- if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { ++ if (qt_readable(fdset.started())) { + if (!_q_startupNotification()) + return false; + } + + bool readyReadEmitted = false; +- if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { ++ if (qt_readable(fdset.stdout())) { + bool canRead = _q_canReadStandardOutput(); + if (processChannel == QProcess::StandardOutput && canRead) + readyReadEmitted = true; + } +- if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) { ++ if (qt_readable(fdset.stderr())) { + bool canRead = _q_canReadStandardError(); + if (processChannel == QProcess::StandardError && canRead) + readyReadEmitted = true; +@@ -1109,13 +1113,13 @@ bool QProcessPrivate::waitForReadyRead(int msecs) + if (readyReadEmitted) + return true; + +- if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) ++ if (qt_writable(fdset.stdin())) + _q_canWrite(); + +- if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { ++ if (qt_readable(fdset.death())) { + if (_q_processDied()) + return false; +- } ++ } + } + return false; + } +@@ -1131,29 +1135,9 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) + stopWatch.start(); + + while (!writeBuffer.isEmpty()) { +- fd_set fdread; +- fd_set fdwrite; +- +- FD_ZERO(&fdread); +- FD_ZERO(&fdwrite); +- +- int nfds = deathPipe[0]; +- FD_SET(deathPipe[0], &fdread); +- +- if (processState == QProcess::Starting) +- add_fd(nfds, childStartedPipe[0], &fdread); +- +- if (stdoutChannel.pipe[0] != -1) +- add_fd(nfds, stdoutChannel.pipe[0], &fdread); +- if (stderrChannel.pipe[0] != -1) +- add_fd(nfds, stderrChannel.pipe[0], &fdread); +- +- +- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) +- add_fd(nfds, stdinChannel.pipe[1], &fdwrite); +- ++ QProcessFDSet fdset(*this); + int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); +- int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); ++ int ret = fdset.poll(timeout); + if (ret < 0) { + break; + } +@@ -1164,24 +1148,24 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) + return false; + } + +- if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { ++ if (qt_readable(fdset.started())) { + if (!_q_startupNotification()) + return false; + } + +- if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) ++ if (qt_writable(fdset.stdin())) + return _q_canWrite(); + +- if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) ++ if (qt_readable(fdset.stdout())) + _q_canReadStandardOutput(); + +- if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) ++ if (qt_readable(fdset.stderr())) + _q_canReadStandardError(); + +- if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { +- if (_q_processDied()) +- return false; +- } ++ if (qt_readable(fdset.death())) { ++ if (_q_processDied()) ++ return false; ++ } + } + + return false; +@@ -1198,29 +1182,9 @@ bool QProcessPrivate::waitForFinished(int msecs) + stopWatch.start(); + + forever { +- fd_set fdread; +- fd_set fdwrite; +- int nfds = -1; +- +- FD_ZERO(&fdread); +- FD_ZERO(&fdwrite); +- +- if (processState == QProcess::Starting) +- add_fd(nfds, childStartedPipe[0], &fdread); +- +- if (stdoutChannel.pipe[0] != -1) +- add_fd(nfds, stdoutChannel.pipe[0], &fdread); +- if (stderrChannel.pipe[0] != -1) +- add_fd(nfds, stderrChannel.pipe[0], &fdread); +- +- if (processState == QProcess::Running) +- add_fd(nfds, deathPipe[0], &fdread); +- +- if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) +- add_fd(nfds, stdinChannel.pipe[1], &fdwrite); +- ++ QProcessFDSet fdset(*this); + int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); +- int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); ++ int ret = fdset.poll(timeout); + if (ret < 0) { + break; + } +@@ -1230,20 +1194,20 @@ bool QProcessPrivate::waitForFinished(int msecs) + return false; + } + +- if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { ++ if (qt_readable(fdset.started())) { + if (!_q_startupNotification()) + return false; + } +- if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) ++ if (qt_writable(fdset.stdin())) + _q_canWrite(); + +- if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) ++ if (qt_readable(fdset.stdout())) + _q_canReadStandardOutput(); + +- if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) ++ if (qt_readable(fdset.stderr())) + _q_canReadStandardError(); + +- if (deathPipe[0] == -1 || FD_ISSET(deathPipe[0], &fdread)) { ++ if (qt_readable(fdset.death())) { + if (_q_processDied()) + return true; + } +@@ -1253,10 +1217,10 @@ bool QProcessPrivate::waitForFinished(int msecs) + + bool QProcessPrivate::waitForWrite(int msecs) + { +- fd_set fdwrite; +- FD_ZERO(&fdwrite); +- FD_SET(stdinChannel.pipe[1], &fdwrite); +- return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; ++ pollfd fd; ++ fd.fd = stdinChannel.pipe[1]; ++ fd.events = POLLIN; ++ return qt_safe_poll(&fd, 1, msecs); + } + + void QProcessPrivate::findExitCode() +diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp +index cc54798..ca178bb 100644 +--- a/src/corelib/kernel/qcore_unix.cpp ++++ b/src/corelib/kernel/qcore_unix.cpp +@@ -103,4 +103,165 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + } + } + ++#ifndef Q_OS_VXWORKS ++ ++int qt_safe_poll(struct pollfd *fds, int nfds, int timeout_ms, bool retry_eintr) ++{ ++ if (nfds == 0) ++ return 0; ++ if (nfds < 0) { ++ errno = EINVAL; ++ return -1; ++ } ++ ++ // Retry on ret == 0 if the deadline has not yet passed because ++ // Linux can return early from the syscall, without setting EINTR. ++ if (timeout_ms < 0) { ++ forever { ++ int ret = ::poll(fds, nfds, -1); ++ if (ret > 0) ++ return ret; ++ if (retry_eintr) { ++ if (ret == 0 || ret == -1 && errno == EINTR) { ++ continue; ++ } else { ++ return -1; ++ } ++ } ++ if (ret == 0) { ++ errno = EINTR; ++ return -1; ++ } ++ return ret; ++ } ++ } ++ ++ timeval previous = qt_gettime(); ++ timeval deadline = previous; ++ deadline.tv_sec += timeout_ms / 1000; ++ deadline.tv_usec += (timeout_ms % 1000) * 1000; ++ if (deadline.tv_usec >= 1000000) { ++ ++deadline.tv_sec; ++ deadline.tv_usec -= 1000000; ++ } ++ int remaining = timeout_ms; ++ ++ forever { ++ int ret = ::poll(fds, nfds, remaining); ++ if (ret > 0) ++ return ret; ++ timeval now = qt_gettime(); ++ if ((now.tv_sec > deadline.tv_sec // past deadline ++ || (now.tv_sec == deadline.tv_sec ++ && now.tv_usec >= deadline.tv_usec)) ++ || (now.tv_sec < previous.tv_sec // time warp ++ || (now.tv_sec == previous.tv_sec ++ && now.tv_usec < previous.tv_usec)) ++ || (ret < 0 && (errno != EINTR || !retry_eintr))) // other error ++ return ret; ++ if (ret == 0 && !retry_eintr) { ++ errno = EINTR; ++ return -1; ++ } ++ remaining = (deadline.tv_sec - now.tv_sec) * 1000 ++ + (deadline.tv_usec - now.tv_usec) / 1000; ++ previous = now; ++ } ++} ++ ++#else ++ ++// Poll emulation for VxWorks. ++ ++static int mark_bad_descriptors(pollfd *fds, int nfds) ++{ ++ fd_set r; ++ FD_ZERO(&r); ++ struct timeval tv; ++ tv.tv_sec = 0; ++ tv.tv_usec = 0; ++ int ret = 0; ++ ++ // Check each descriptor invidually for badness. ++ for (int i = 0; i < nfds; ++i) { ++ pollfd &fd(fds[i]); ++ if (fd.fd >= 0) { ++ FD_SET(fd.fd, &r); ++ int ret = qt_safe_select(fd.fd + 1, &r, NULL, NULL, &tv); ++ FD_CLR(fd.fd, &r); ++ if (ret < 0 && errno == EBADF) { ++ fd.revents = POLLNVAL; ++ ++ret; ++ } ++ } ++ } ++ Q_ASSERT(ret > 0); ++ return ret; ++} ++ ++int qt_safe_poll(pollfd *fds, int nfds, int timeout, bool retry_eintr) ++{ ++ fd_set r, w; ++ FD_ZERO(&r); ++ FD_ZERO(&w); ++ int maxfd = -1; ++ ++ // Extract the watched descriptors. ++ for (int i = 0; i < nfds; ++i) { ++ pollfd &fd(fds[i]); ++ if (fd.fd >= 0 && fd.fd < FD_SETSIZE) { ++ if (fd.events & POLLIN) { ++ FD_SET(fd.fd, &r); ++ if (fd.fd > maxfd) ++ maxfd = fd.fd; ++ } ++ if (fd.events & POLLOUT) { ++ FD_SET(fd.fd, &w); ++ if (fd.fd > maxfd) ++ maxfd = fd.fd; ++ } ++ } ++ } ++ ++ // If timeout is negative, wait indefinitely for activity. ++ timeval tv; ++ timeval *ptv; ++ if (timeout >= 0) { ++ tv.tv_sec = timeout / 1000; ++ tv.tv_usec = (timeout % 1000) * 1000; ++ ptv = &tv; ++ } else ++ ptv = NULL; ++ ++ int ret; ++ if (retry_eintr) ++ ret = qt_safe_select(maxfd + 1, &r, &w, NULL, ptv); ++ else ++ ret = ::select(maxfd + 1, &r, &w, NULL, ptv); ++ if (ret < 0 && errno == EBADF) { ++ return mark_bad_descriptors(fds, nfds); ++ } ++ if (ret <= 0) ++ return ret; ++ ++ // Set the revents flags. ++ ret = 0; ++ for (int i = 0; i < nfds; ++i) { ++ pollfd &fd(fds[i]); ++ fd.revents = 0; ++ if (fd.fd >= 0 && fd.fd < FD_SETSIZE) { ++ if ((fd.events & POLLIN) && FD_ISSET(fd.fd, &r)) ++ fd.revents |= POLLIN; ++ if ((fd.events & POLLOUT) && FD_ISSET(fd.fd, &w)) ++ fd.revents |= POLLOUT; ++ if (fd.revents) ++ ++ret; ++ } ++ } ++ Q_ASSERT(ret > 0); ++ return ret; ++} ++ ++#endif // Q_OS_VXWORKS ++ + QT_END_NAMESPACE +diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h +index 6342b03..f7f4767 100644 +--- a/src/corelib/kernel/qcore_unix_p.h ++++ b/src/corelib/kernel/qcore_unix_p.h +@@ -71,6 +71,8 @@ + + #if defined(Q_OS_VXWORKS) + # include ++#else ++# include + #endif + + struct sockaddr; +@@ -341,6 +343,36 @@ void qt_nanosleep(timespec amount); + Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *tv); + ++#ifdef Q_OS_VXWORKS ++// Poll emulation for VxWorks. Provided by on other systems. ++ ++struct pollfd { ++ int fd; ++ short events; ++ short revents; ++}; ++ ++#define POLLIN 1 ++#define POLLOUT 2 ++#define POLLERR 4 ++#define POLLHUP 8 ++#define POLLNVAL 16 ++#endif ++ ++inline bool qt_readable(const pollfd &fd) ++{ ++ return fd.fd >= 0 && (fd.revents & (POLLIN | POLLHUP | POLLERR | POLLNVAL)) != 0; ++} ++ ++inline bool qt_writable(const pollfd &fd) ++{ ++ return fd.fd >= 0 && (fd.revents & (POLLOUT | POLLHUP | POLLERR | POLLNVAL)) != 0; ++} ++ ++// Deprecated due to FD_SETSIZE limitation, use qt_safe_poll instead. ++Q_CORE_EXPORT int qt_safe_poll(pollfd *fds, int nfds, int timeout, ++ bool retry_eintr = true); ++ + // according to X/OPEN we have to define semun ourselves + // we use prefix as on some systems sem.h will have it + struct semid_ds; +diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp +index 2bcf1ac..efb8128 100644 +--- a/src/network/socket/qlocalserver_unix.cpp ++++ b/src/network/socket/qlocalserver_unix.cpp +@@ -293,16 +293,11 @@ void QLocalServerPrivate::_q_onNewConnection() + + void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut) + { +- fd_set readfds; +- FD_ZERO(&readfds); +- FD_SET(listenSocket, &readfds); ++ struct pollfd fd; ++ fd.fd = listenSocket; ++ fd.events = POLLIN; + +- timeval timeout; +- timeout.tv_sec = msec / 1000; +- timeout.tv_usec = (msec % 1000) * 1000; +- +- int result = -1; +- result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout); ++ int result = qt_safe_poll(&fd, 1, msec); + if (-1 == result) { + setError(QLatin1String("QLocalServer::waitForNewConnection")); + closeServer(); +diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp +index 49eb71a..c598c2b 100644 +--- a/src/network/socket/qlocalsocket_unix.cpp ++++ b/src/network/socket/qlocalsocket_unix.cpp +@@ -56,10 +56,6 @@ + #include + #include + +-#ifdef Q_OS_VXWORKS +-# include +-#endif +- + #define QT_CONNECT_TIMEOUT 30000 + + QT_BEGIN_NAMESPACE +@@ -524,25 +520,16 @@ bool QLocalSocket::waitForConnected(int msec) + if (state() != ConnectingState) + return (state() == ConnectedState); + +- fd_set fds; +- FD_ZERO(&fds); +- FD_SET(d->connectingSocket, &fds); +- +- timeval timeout; +- timeout.tv_sec = msec / 1000; +- timeout.tv_usec = (msec % 1000) * 1000; ++ pollfd fd; ++ fd.fd = d->connectingSocket; ++ fd.events = POLLIN | POLLOUT; + +- // timeout can not be 0 or else select will return an error. +- if (0 == msec) +- timeout.tv_usec = 1000; +- +- int result = -1; +- // on Linux timeout will be updated by select, but _not_ on other systems. ++ int result; + QElapsedTimer timer; ++ int remaining = msec > 0 ? msec : 1000; + timer.start(); +- while (state() == ConnectingState +- && (-1 == msec || timer.elapsed() < msec)) { +- result = ::select(d->connectingSocket + 1, &fds, 0, 0, &timeout); ++ while (state() == ConnectingState) { ++ result = qt_safe_poll(&fd, 1, remaining, /* retry_eintr */ false); + if (-1 == result && errno != EINTR) { + d->errorOccurred( QLocalSocket::UnknownSocketError, + QLatin1String("QLocalSocket::waitForConnected")); +@@ -550,6 +537,11 @@ bool QLocalSocket::waitForConnected(int msec) + } + if (result > 0) + d->_q_connectToSocket(); ++ if (msec >= 0) { ++ remaining = timer.elapsed() - msec; ++ if (remaining < 0) ++ break; ++ } + } + + return (state() == ConnectedState); +diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp +index 4f3408b..a1bb298 100644 +--- a/src/network/socket/qnativesocketengine_unix.cpp ++++ b/src/network/socket/qnativesocketengine_unix.cpp +@@ -1122,48 +1122,40 @@ qint64 QNativeSocketEnginePrivate::nativeRead(char *data, qint64 maxSize) + + int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const + { +- fd_set fds; +- FD_ZERO(&fds); +- FD_SET(socketDescriptor, &fds); +- +- struct timeval tv; +- tv.tv_sec = timeout / 1000; +- tv.tv_usec = (timeout % 1000) * 1000; +- +- int retval; +- if (selectForRead) +- retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); +- else +- retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); +- +- return retval; ++ struct pollfd fd; ++ fd.fd = socketDescriptor; ++ if (selectForRead) { ++ fd.events = POLLIN; ++ } else { ++ fd.events = POLLOUT; ++ } ++ return qt_safe_poll(&fd, 1, timeout); + } + + int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite, + bool *selectForRead, bool *selectForWrite) const + { +- fd_set fdread; +- FD_ZERO(&fdread); ++ struct pollfd fd; ++ fd.fd = socketDescriptor; + if (checkRead) +- FD_SET(socketDescriptor, &fdread); +- +- fd_set fdwrite; +- FD_ZERO(&fdwrite); ++ fd.events = POLLIN; ++ else ++ fd.events = 0; + if (checkWrite) +- FD_SET(socketDescriptor, &fdwrite); +- +- struct timeval tv; +- tv.tv_sec = timeout / 1000; +- tv.tv_usec = (timeout % 1000) * 1000; +- +- int ret; +- ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); +- ++ fd.events |= POLLOUT; ++ int ret = qt_safe_poll(&fd, 1, timeout); + if (ret <= 0) +- return ret; +- *selectForRead = FD_ISSET(socketDescriptor, &fdread); +- *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite); +- ++ return ret; ++ bool r = (fd.revents & (POLLIN | POLLHUP | POLLERR)) != 0; ++ bool w = (fd.revents & (POLLOUT | POLLHUP | POLLERR)) != 0; ++ // Emulate the return value from select(2). ++ ret = 0; ++ if (r) ++ ++ret; ++ if (w) ++ ++ret; ++ *selectForRead = r; ++ *selectForWrite = w; + return ret; + } + diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec index 170f540..d07a597 100644 --- a/qt5-qtbase.spec +++ b/qt5-qtbase.spec @@ -8,7 +8,7 @@ Summary: Qt5 - QtBase components Name: qt5-qtbase Version: 5.0.2 -Release: 4%{?dist} +Release: 5%{?dist} # See LGPL_EXCEPTIONS.txt, LICENSE.GPL3, respectively, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions @@ -21,6 +21,11 @@ Patch1: qtbase-opensource-src-5.0.2-lowmem.patch # support multilib optflags Patch2: qtbase-multilib_optflags.patch + +# upstreamable patches +# support poll +patch50: qt5-poll.patch + ##upstream patches # https://bugzilla.redhat.com/929227 # https://codereview.qt-project.org/52778 @@ -147,6 +152,8 @@ Qt5 libraries used for drawing widgets and OpenGL items. # drop backup file(s), else they get installed too, http://bugzilla.redhat.com/639463 rm -fv mkspecs/linux-g++*/qmake.conf.multilib-optflags +%patch50 -p1 -b .poll + %patch100 -p1 -b .cmake_path %patch1341 -p1 -b .0341 @@ -476,6 +483,9 @@ popd %changelog +* Wed May 08 2013 Than Ngo - 5.0.2-5 +- add poll support, thanks to fweimer@redhat.com + * Thu Apr 18 2013 Rex Dieter 5.0.2-4 - respin lowmem patch to apply (unconditionally) to gcc-4.7.2 too