Blame SOURCES/qt5-poll.patch

2d2b1a
diff --git a/config.tests/unix/poll/poll.cpp b/config.tests/unix/poll/poll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..06ae038
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/poll/poll.cpp
2d2b1a
@@ -0,0 +1,45 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the config.tests of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include <poll.h>
2d2b1a
+
2d2b1a
+int main()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd;
2d2b1a
+
2d2b1a
+    pfd.fd = -1;
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    return ::poll(&pfd, 1, 0);
2d2b1a
+}
2d2b1a
diff --git a/config.tests/unix/poll/poll.pro b/config.tests/unix/poll/poll.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..70121b4
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/poll/poll.pro
2d2b1a
@@ -0,0 +1,2 @@
2d2b1a
+SOURCES = poll.cpp
2d2b1a
+CONFIG -= qt
2d2b1a
diff --git a/config.tests/unix/pollts/poll/poll.cpp b/config.tests/unix/pollts/poll/poll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..06ae038
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/poll/poll.cpp
2d2b1a
@@ -0,0 +1,45 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the config.tests of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include <poll.h>
2d2b1a
+
2d2b1a
+int main()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd;
2d2b1a
+
2d2b1a
+    pfd.fd = -1;
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    return ::poll(&pfd, 1, 0);
2d2b1a
+}
2d2b1a
diff --git a/config.tests/unix/pollts/poll/poll.pro b/config.tests/unix/pollts/poll/poll.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..70121b4
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/poll/poll.pro
2d2b1a
@@ -0,0 +1,2 @@
2d2b1a
+SOURCES = poll.cpp
2d2b1a
+CONFIG -= qt
2d2b1a
diff --git a/config.tests/unix/pollts/pollts.cpp b/config.tests/unix/pollts/pollts.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..c2d1940
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/pollts.cpp
2d2b1a
@@ -0,0 +1,51 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the config.tests of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include <poll.h>
2d2b1a
+#include <signal.h>
2d2b1a
+#include <time.h>
2d2b1a
+
2d2b1a
+int main()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd;
2d2b1a
+    struct timespec ts;
2d2b1a
+
2d2b1a
+    pfd.fd = -1;
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    ts.tv_sec = 0;
2d2b1a
+    ts.tv_nsec = 0;
2d2b1a
+
2d2b1a
+    return ::pollts(&pfd, 1, &ts, nullptr);
2d2b1a
+}
2d2b1a
diff --git a/config.tests/unix/pollts/pollts/poll/poll.cpp b/config.tests/unix/pollts/pollts/poll/poll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..06ae038
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/pollts/poll/poll.cpp
2d2b1a
@@ -0,0 +1,45 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the config.tests of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include <poll.h>
2d2b1a
+
2d2b1a
+int main()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd;
2d2b1a
+
2d2b1a
+    pfd.fd = -1;
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    return ::poll(&pfd, 1, 0);
2d2b1a
+}
2d2b1a
diff --git a/config.tests/unix/pollts/pollts/poll/poll.pro b/config.tests/unix/pollts/pollts/poll/poll.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..70121b4
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/pollts/poll/poll.pro
2d2b1a
@@ -0,0 +1,2 @@
2d2b1a
+SOURCES = poll.cpp
2d2b1a
+CONFIG -= qt
2d2b1a
diff --git a/config.tests/unix/pollts/pollts/pollts.cpp b/config.tests/unix/pollts/pollts/pollts.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..8b13789
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/pollts/pollts.cpp
2d2b1a
@@ -0,0 +1 @@
2d2b1a
+
2d2b1a
diff --git a/config.tests/unix/pollts/pollts/pollts.pro b/config.tests/unix/pollts/pollts/pollts.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..5109dc3
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/pollts/pollts/pollts.pro
2d2b1a
@@ -0,0 +1,2 @@
2d2b1a
+SOURCES = pollts.cpp
2d2b1a
+CONFIG -= qt
2d2b1a
diff --git a/config.tests/unix/ppoll/ppoll.cpp b/config.tests/unix/ppoll/ppoll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..5b0cc4d
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/ppoll/ppoll.cpp
2d2b1a
@@ -0,0 +1,51 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the config.tests of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include <signal.h>
2d2b1a
+#include <poll.h>
2d2b1a
+
2d2b1a
+int main()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd;
2d2b1a
+    struct timespec ts;
2d2b1a
+
2d2b1a
+    pfd.fd = -1;
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    ts.tv_sec = 0;
2d2b1a
+    ts.tv_nsec = 0;
2d2b1a
+
2d2b1a
+    return ::ppoll(&pfd, 1, &ts, nullptr);
2d2b1a
+}
2d2b1a
+
2d2b1a
diff --git a/config.tests/unix/ppoll/ppoll.pro b/config.tests/unix/ppoll/ppoll.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..d08a8a0
2d2b1a
--- /dev/null
2d2b1a
+++ b/config.tests/unix/ppoll/ppoll.pro
2d2b1a
@@ -0,0 +1,2 @@
2d2b1a
+SOURCES = ppoll.cpp
2d2b1a
+CONFIG -= qt
2d2b1a
diff --git a/configure b/configure
2d2b1a
index 7651e29..9be4179 100755
2d2b1a
--- a/configure
2d2b1a
+++ b/configure
2d2b1a
@@ -729,6 +729,7 @@ CFG_GETIFADDRS=auto
2d2b1a
 CFG_INOTIFY=auto
2d2b1a
 CFG_EVENTFD=auto
2d2b1a
 CFG_CLOEXEC=no
2d2b1a
+CFG_POLL=auto
2d2b1a
 CFG_RPATH=yes
2d2b1a
 CFG_FRAMEWORK=auto
2d2b1a
 CFG_USE_GOLD_LINKER=auto
2d2b1a
@@ -6043,6 +6044,16 @@ if compileTest unix/cloexec "cloexec"; then
2d2b1a
     CFG_CLOEXEC=yes
2d2b1a
 fi
2d2b1a
2d2b1a
+if compileTest unix/ppoll "ppoll"; then
2d2b1a
+    CFG_POLL="ppoll"
2d2b1a
+elif compileTest unix/pollts "pollts"; then
2d2b1a
+    CFG_POLL="pollts"
2d2b1a
+elif compileTest unix/poll "poll"; then
2d2b1a
+    CFG_POLL="poll"
2d2b1a
+else
2d2b1a
+    CFG_POLL="select"
2d2b1a
+fi
2d2b1a
+
2d2b1a
 if [ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_SECURETRANSPORT" != "no" ] && ([ "$CFG_OPENSSL" = "no" ] || [ "$CFG_OPENSSL" = "auto" ]); then
2d2b1a
     CFG_SECURETRANSPORT=yes
2d2b1a
     CFG_OPENSSL=no
2d2b1a
@@ -6350,6 +6361,10 @@ fi
2d2b1a
 if [ "$CFG_CLOEXEC" = "yes" ]; then
2d2b1a
     QT_CONFIG="$QT_CONFIG threadsafe-cloexec"
2d2b1a
 fi
2d2b1a
+if [ "$CFG_POLL" = "select" ]; then
2d2b1a
+    QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_NATIVE_POLL"
2d2b1a
+fi
2d2b1a
+QT_CONFIG="$QT_CONFIG poll_$CFG_POLL"
2d2b1a
 if [ "$CFG_LIBJPEG" = "no" ]; then
2d2b1a
     CFG_JPEG="no"
2d2b1a
 elif [ "$CFG_LIBJPEG" = "system" ]; then
2d2b1a
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
2d2b1a
index 8eb5ac9..74a0c41 100644
2d2b1a
--- a/src/corelib/io/qprocess_unix.cpp
2d2b1a
+++ b/src/corelib/io/qprocess_unix.cpp
2d2b1a
@@ -115,11 +115,52 @@ QT_BEGIN_NAMESPACE
2d2b1a
 // so we will use 512
2d2b1a
 static const int errorBufferMax = 512;
2d2b1a
2d2b1a
-static inline void add_fd(int &nfds, int fd, fd_set *fdset)
2d2b1a
+namespace {
2d2b1a
+struct QProcessPoller
2d2b1a
 {
2d2b1a
-    FD_SET(fd, fdset);
2d2b1a
-    if ((fd) > nfds)
2d2b1a
-        nfds = fd;
2d2b1a
+    QProcessPoller(const QProcessPrivate &proc;;
2d2b1a
+
2d2b1a
+    int poll(int timeout);
2d2b1a
+
2d2b1a
+    pollfd &stdinPipe() { return pfds[0]; }
2d2b1a
+    pollfd &stdoutPipe() { return pfds[1]; }
2d2b1a
+    pollfd &stderrPipe() { return pfds[2]; }
2d2b1a
+    pollfd &forkfd() { return pfds[3]; }
2d2b1a
+    pollfd &childStartedPipe() { return pfds[4]; }
2d2b1a
+
2d2b1a
+    enum { n_pfds = 5 };
2d2b1a
+    pollfd pfds[n_pfds];
2d2b1a
+};
2d2b1a
+
2d2b1a
+QProcessPoller::QProcessPoller(const QProcessPrivate &proc)
2d2b1a
+{
2d2b1a
+    for (int i = 0; i < n_pfds; i++)
2d2b1a
+        pfds[i] = qt_make_pollfd(-1, POLLIN);
2d2b1a
+
2d2b1a
+    stdoutPipe().fd = proc.stdoutChannel.pipe[0];
2d2b1a
+    stderrPipe().fd = proc.stderrChannel.pipe[0];
2d2b1a
+
2d2b1a
+    if (!proc.stdinChannel.buffer.isEmpty()) {
2d2b1a
+        stdinPipe().fd = proc.stdinChannel.pipe[1];
2d2b1a
+        stdinPipe().events = POLLOUT;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    forkfd().fd = proc.forkfd;
2d2b1a
+
2d2b1a
+    if (proc.processState == QProcess::Starting)
2d2b1a
+        childStartedPipe().fd = proc.childStartedPipe[0];
2d2b1a
+}
2d2b1a
+
2d2b1a
+int QProcessPoller::poll(int timeout)
2d2b1a
+{
2d2b1a
+    const nfds_t nfds = (childStartedPipe().fd == -1) ? 4 : 5;
2d2b1a
+    return qt_poll_msecs(pfds, nfds, timeout);
2d2b1a
+}
2d2b1a
+} // anonymous namespace
2d2b1a
+
2d2b1a
+static bool qt_pollfd_check(const pollfd &pfd, short revents)
2d2b1a
+{
2d2b1a
+    return pfd.fd >= 0 && (pfd.revents & (revents | POLLHUP | POLLERR | POLLNVAL)) != 0;
2d2b1a
 }
2d2b1a
2d2b1a
 static int qt_create_pipe(int *pipe)
2d2b1a
@@ -812,10 +853,9 @@ bool QProcessPrivate::waitForStarted(int msecs)
2d2b1a
            childStartedPipe[0]);
2d2b1a
 #endif
2d2b1a
2d2b1a
-    fd_set fds;
2d2b1a
-    FD_ZERO(&fds);
2d2b1a
-    FD_SET(childStartedPipe[0], &fds);
2d2b1a
-    if (qt_select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) {
2d2b1a
+    pollfd pfd = qt_make_pollfd(childStartedPipe[0], POLLIN);
2d2b1a
+
2d2b1a
+    if (qt_poll_msecs(&pfd, 1, msecs) == 0) {
2d2b1a
         setError(QProcess::Timedout);
2d2b1a
 #if defined (QPROCESS_DEBUG)
2d2b1a
         qDebug("QProcessPrivate::waitForStarted(%d) == false (timed out)", msecs);
2d2b1a
@@ -855,31 +895,13 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
2d2b1a
 #endif
2d2b1a
2d2b1a
     forever {
2d2b1a
-        fd_set fdread;
2d2b1a
-        fd_set fdwrite;
2d2b1a
-
2d2b1a
-        FD_ZERO(&fdread);
2d2b1a
-        FD_ZERO(&fdwrite);
2d2b1a
-
2d2b1a
-        int nfds = forkfd;
2d2b1a
-        FD_SET(forkfd, &fdread);
2d2b1a
-
2d2b1a
-        if (processState == QProcess::Starting)
2d2b1a
-            add_fd(nfds, childStartedPipe[0], &fdread);
2d2b1a
-
2d2b1a
-        if (stdoutChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stdoutChannel.pipe[0], &fdread);
2d2b1a
-        if (stderrChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stderrChannel.pipe[0], &fdread);
2d2b1a
-
2d2b1a
-        if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
2d2b1a
-            add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
2d2b1a
+        QProcessPoller poller(*this);
2d2b1a
2d2b1a
         int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
2d2b1a
 #ifdef Q_OS_BLACKBERRY
2d2b1a
         int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
 #else
2d2b1a
-        int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
+        int ret = poller.poll(timeout);
2d2b1a
 #endif
2d2b1a
         if (ret < 0) {
2d2b1a
             break;
2d2b1a
@@ -889,18 +911,18 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
2d2b1a
             return false;
2d2b1a
         }
2d2b1a
2d2b1a
-        if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
2d2b1a
             if (!_q_startupNotification())
2d2b1a
                 return false;
2d2b1a
         }
2d2b1a
2d2b1a
         bool readyReadEmitted = false;
2d2b1a
-        if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.stdoutPipe(), POLLIN)) {
2d2b1a
             bool canRead = _q_canReadStandardOutput();
2d2b1a
             if (processChannel == QProcess::StandardOutput && canRead)
2d2b1a
                 readyReadEmitted = true;
2d2b1a
         }
2d2b1a
-        if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.stderrPipe(), POLLIN)) {
2d2b1a
             bool canRead = _q_canReadStandardError();
2d2b1a
             if (processChannel == QProcess::StandardError && canRead)
2d2b1a
                 readyReadEmitted = true;
2d2b1a
@@ -908,10 +930,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs)
2d2b1a
         if (readyReadEmitted)
2d2b1a
             return true;
2d2b1a
2d2b1a
-        if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
2d2b1a
+        if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
2d2b1a
             _q_canWrite();
2d2b1a
2d2b1a
-        if (forkfd == -1 || FD_ISSET(forkfd, &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
2d2b1a
             if (_q_processDied())
2d2b1a
                 return false;
2d2b1a
         }
2d2b1a
@@ -933,32 +955,13 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
2d2b1a
 #endif
2d2b1a
2d2b1a
     while (!stdinChannel.buffer.isEmpty()) {
2d2b1a
-        fd_set fdread;
2d2b1a
-        fd_set fdwrite;
2d2b1a
-
2d2b1a
-        FD_ZERO(&fdread);
2d2b1a
-        FD_ZERO(&fdwrite);
2d2b1a
-
2d2b1a
-        int nfds = forkfd;
2d2b1a
-        FD_SET(forkfd, &fdread);
2d2b1a
-
2d2b1a
-        if (processState == QProcess::Starting)
2d2b1a
-            add_fd(nfds, childStartedPipe[0], &fdread);
2d2b1a
-
2d2b1a
-        if (stdoutChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stdoutChannel.pipe[0], &fdread);
2d2b1a
-        if (stderrChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stderrChannel.pipe[0], &fdread);
2d2b1a
-
2d2b1a
-
2d2b1a
-        if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
2d2b1a
-            add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
2d2b1a
+        QProcessPoller poller(*this);
2d2b1a
2d2b1a
         int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
2d2b1a
 #ifdef Q_OS_BLACKBERRY
2d2b1a
         int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
 #else
2d2b1a
-        int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
+        int ret = poller.poll(timeout);
2d2b1a
 #endif
2d2b1a
         if (ret < 0) {
2d2b1a
             break;
2d2b1a
@@ -969,21 +972,21 @@ bool QProcessPrivate::waitForBytesWritten(int msecs)
2d2b1a
             return false;
2d2b1a
         }
2d2b1a
2d2b1a
-        if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
2d2b1a
             if (!_q_startupNotification())
2d2b1a
                 return false;
2d2b1a
         }
2d2b1a
2d2b1a
-        if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
2d2b1a
+        if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
2d2b1a
             return _q_canWrite();
2d2b1a
2d2b1a
-        if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
2d2b1a
+        if (qt_pollfd_check(poller.stdoutPipe(), POLLIN))
2d2b1a
             _q_canReadStandardOutput();
2d2b1a
2d2b1a
-        if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
2d2b1a
+        if (qt_pollfd_check(poller.stderrPipe(), POLLIN))
2d2b1a
             _q_canReadStandardError();
2d2b1a
2d2b1a
-        if (forkfd == -1 || FD_ISSET(forkfd, &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
2d2b1a
             if (_q_processDied())
2d2b1a
                 return false;
2d2b1a
         }
2d2b1a
@@ -1006,32 +1009,13 @@ bool QProcessPrivate::waitForFinished(int msecs)
2d2b1a
 #endif
2d2b1a
2d2b1a
     forever {
2d2b1a
-        fd_set fdread;
2d2b1a
-        fd_set fdwrite;
2d2b1a
-        int nfds = -1;
2d2b1a
-
2d2b1a
-        FD_ZERO(&fdread);
2d2b1a
-        FD_ZERO(&fdwrite);
2d2b1a
-
2d2b1a
-        if (processState == QProcess::Starting)
2d2b1a
-            add_fd(nfds, childStartedPipe[0], &fdread);
2d2b1a
-
2d2b1a
-        if (stdoutChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stdoutChannel.pipe[0], &fdread);
2d2b1a
-        if (stderrChannel.pipe[0] != -1)
2d2b1a
-            add_fd(nfds, stderrChannel.pipe[0], &fdread);
2d2b1a
-
2d2b1a
-        if (processState == QProcess::Running && forkfd != -1)
2d2b1a
-            add_fd(nfds, forkfd, &fdread);
2d2b1a
-
2d2b1a
-        if (!stdinChannel.buffer.isEmpty() && stdinChannel.pipe[1] != -1)
2d2b1a
-            add_fd(nfds, stdinChannel.pipe[1], &fdwrite);
2d2b1a
+        QProcessPoller poller(*this);
2d2b1a
2d2b1a
         int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
2d2b1a
 #ifdef Q_OS_BLACKBERRY
2d2b1a
         int ret = bb_select(notifiers, nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
 #else
2d2b1a
-        int ret = qt_select_msecs(nfds + 1, &fdread, &fdwrite, timeout);
2d2b1a
+        int ret = poller.poll(timeout);
2d2b1a
 #endif
2d2b1a
         if (ret < 0) {
2d2b1a
             break;
2d2b1a
@@ -1041,20 +1025,20 @@ bool QProcessPrivate::waitForFinished(int msecs)
2d2b1a
             return false;
2d2b1a
         }
2d2b1a
2d2b1a
-        if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.childStartedPipe(), POLLIN)) {
2d2b1a
             if (!_q_startupNotification())
2d2b1a
                 return false;
2d2b1a
         }
2d2b1a
-        if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite))
2d2b1a
+        if (qt_pollfd_check(poller.stdinPipe(), POLLOUT))
2d2b1a
             _q_canWrite();
2d2b1a
2d2b1a
-        if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread))
2d2b1a
+        if (qt_pollfd_check(poller.stdoutPipe(), POLLIN))
2d2b1a
             _q_canReadStandardOutput();
2d2b1a
2d2b1a
-        if (stderrChannel.pipe[0] != -1 && FD_ISSET(stderrChannel.pipe[0], &fdread))
2d2b1a
+        if (qt_pollfd_check(poller.stderrPipe(), POLLIN))
2d2b1a
             _q_canReadStandardError();
2d2b1a
2d2b1a
-        if (forkfd == -1 || FD_ISSET(forkfd, &fdread)) {
2d2b1a
+        if (qt_pollfd_check(poller.forkfd(), POLLIN)) {
2d2b1a
             if (_q_processDied())
2d2b1a
                 return true;
2d2b1a
         }
2d2b1a
@@ -1064,10 +1048,8 @@ bool QProcessPrivate::waitForFinished(int msecs)
2d2b1a
2d2b1a
 bool QProcessPrivate::waitForWrite(int msecs)
2d2b1a
 {
2d2b1a
-    fd_set fdwrite;
2d2b1a
-    FD_ZERO(&fdwrite);
2d2b1a
-    FD_SET(stdinChannel.pipe[1], &fdwrite);
2d2b1a
-    return qt_select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1;
2d2b1a
+    pollfd pfd = qt_make_pollfd(stdinChannel.pipe[1], POLLOUT);
2d2b1a
+    return qt_poll_msecs(&pfd, 1, msecs < 0 ? 0 : msecs) == 1;
2d2b1a
 }
2d2b1a
2d2b1a
 void QProcessPrivate::findExitCode()
2d2b1a
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
2d2b1a
index bc93791..ff64b4e 100644
2d2b1a
--- a/src/corelib/kernel/kernel.pri
2d2b1a
+++ b/src/corelib/kernel/kernel.pri
2d2b1a
@@ -143,8 +143,14 @@ unix|integrity {
2d2b1a
             kernel/qcore_unix_p.h \
2d2b1a
             kernel/qcrashhandler_p.h \
2d2b1a
             kernel/qeventdispatcher_unix_p.h \
2d2b1a
+            kernel/qpoll_p.h \
2d2b1a
             kernel/qtimerinfo_unix_p.h
2d2b1a
2d2b1a
+    contains(QT_CONFIG, poll_select): SOURCES += kernel/qpoll.cpp
2d2b1a
+    contains(QT_CONFIG, poll_poll): DEFINES += QT_HAVE_POLL
2d2b1a
+    contains(QT_CONFIG, poll_ppoll): DEFINES += QT_HAVE_POLL QT_HAVE_PPOLL
2d2b1a
+    contains(QT_CONFIG, poll_pollts): DEFINES += QT_HAVE_POLL QT_HAVE_POLLTS
2d2b1a
+
2d2b1a
     contains(QT_CONFIG, glib) {
2d2b1a
         SOURCES += \
2d2b1a
             kernel/qeventdispatcher_glib.cpp
2d2b1a
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
2d2b1a
index 5695cb3..2ffc746 100644
2d2b1a
--- a/src/corelib/kernel/qcore_unix.cpp
2d2b1a
+++ b/src/corelib/kernel/qcore_unix.cpp
2d2b1a
@@ -56,6 +56,11 @@
2d2b1a
2d2b1a
 QT_BEGIN_NAMESPACE
2d2b1a
2d2b1a
+#if !defined(QT_HAVE_PPOLL) && defined(QT_HAVE_POLLTS)
2d2b1a
+# define ppoll pollts
2d2b1a
+# define QT_HAVE_PPOLL
2d2b1a
+#endif
2d2b1a
+
2d2b1a
 static inline bool time_update(struct timespec *tv, const struct timespec &start,
2d2b1a
                                const struct timespec &timeout)
2d2b1a
 {
2d2b1a
@@ -85,9 +90,7 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
2d2b1a
 #ifndef Q_OS_QNX
2d2b1a
         ret = ::pselect(nfds, fdread, fdwrite, fdexcept, &timeout, 0);
2d2b1a
 #else
2d2b1a
-        timeval timeoutVal;
2d2b1a
-        timeoutVal.tv_sec = timeout.tv_sec;
2d2b1a
-        timeoutVal.tv_usec = timeout.tv_nsec / 1000;
2d2b1a
+        timeval timeoutVal = timespecToTimeval(timeout);
2d2b1a
         ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeoutVal);
2d2b1a
 #endif
2d2b1a
         if (ret != -1 || errno != EINTR)
2d2b1a
@@ -102,17 +105,82 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
2d2b1a
     }
2d2b1a
 }
2d2b1a
2d2b1a
+static inline struct timespec millisecsToTimespec(const unsigned int ms)
2d2b1a
+{
2d2b1a
+    struct timespec tv;
2d2b1a
+
2d2b1a
+    tv.tv_sec = ms / 1000;
2d2b1a
+    tv.tv_nsec = (ms % 1000) * 1000 * 1000;
2d2b1a
+
2d2b1a
+    return tv;
2d2b1a
+}
2d2b1a
+
2d2b1a
 int qt_select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout)
2d2b1a
 {
2d2b1a
     if (timeout < 0)
2d2b1a
         return qt_safe_select(nfds, fdread, fdwrite, 0, 0);
2d2b1a
2d2b1a
-    struct timespec tv;
2d2b1a
-    tv.tv_sec = timeout / 1000;
2d2b1a
-    tv.tv_nsec = (timeout % 1000) * 1000 * 1000;
2d2b1a
+    struct timespec tv = millisecsToTimespec(timeout);
2d2b1a
     return qt_safe_select(nfds, fdread, fdwrite, 0, &tv;;
2d2b1a
 }
2d2b1a
2d2b1a
+#if !defined(QT_HAVE_PPOLL) && defined(QT_HAVE_POLL)
2d2b1a
+static inline int timespecToMillisecs(const struct timespec *ts)
2d2b1a
+{
2d2b1a
+    return (ts == NULL) ? -1 :
2d2b1a
+           (ts->tv_sec * 1000) + (ts->tv_nsec / 1000000);
2d2b1a
+}
2d2b1a
+#endif
2d2b1a
+
2d2b1a
+// defined in qpoll.cpp
2d2b1a
+int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
2d2b1a
+
2d2b1a
+static inline int qt_ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
2d2b1a
+{
2d2b1a
+#if defined(QT_HAVE_PPOLL)
2d2b1a
+    return ::ppoll(fds, nfds, timeout_ts, Q_NULLPTR);
2d2b1a
+#elif defined(QT_HAVE_POLL)
2d2b1a
+    return ::poll(fds, nfds, timespecToMillisecs(timeout_ts));
2d2b1a
+#else
2d2b1a
+    return qt_poll(fds, nfds, timeout_ts);
2d2b1a
+#endif
2d2b1a
+}
2d2b1a
+
2d2b1a
+
2d2b1a
+/*!
2d2b1a
+    \internal
2d2b1a
+
2d2b1a
+    Behaves as close to POSIX poll(2) as practical but may be implemented
2d2b1a
+    using select(2) where necessary. In that case, returns -1 and sets errno
2d2b1a
+    to EINVAL if passed any descriptor greater than or equal to FD_SETSIZE.
2d2b1a
+*/
2d2b1a
+int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
2d2b1a
+{
2d2b1a
+    if (!timeout_ts) {
2d2b1a
+        // no timeout -> block forever
2d2b1a
+        int ret;
2d2b1a
+        EINTR_LOOP(ret, qt_ppoll(fds, nfds, Q_NULLPTR));
2d2b1a
+        return ret;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    timespec start = qt_gettime();
2d2b1a
+    timespec timeout = *timeout_ts;
2d2b1a
+
2d2b1a
+    // loop and recalculate the timeout as needed
2d2b1a
+    forever {
2d2b1a
+        const int ret = qt_ppoll(fds, nfds, &timeout);
2d2b1a
+        if (ret != -1 || errno != EINTR)
2d2b1a
+            return ret;
2d2b1a
+
2d2b1a
+        // recalculate the timeout
2d2b1a
+        if (!time_update(&timeout, start, *timeout_ts)) {
2d2b1a
+            // timeout during update
2d2b1a
+            // or clock reset, fake timeout error
2d2b1a
+            return 0;
2d2b1a
+        }
2d2b1a
+    }
2d2b1a
+}
2d2b1a
+
2d2b1a
 #ifdef Q_OS_BLACKBERRY
2d2b1a
 // The BlackBerry event dispatcher uses bps_get_event. Unfortunately, already registered
2d2b1a
 // socket notifiers are disabled by a call to select. This is to rearm the standard streams.
2d2b1a
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
2d2b1a
index f80dcb5..fc3f63b 100644
2d2b1a
--- a/src/corelib/kernel/qcore_unix_p.h
2d2b1a
+++ b/src/corelib/kernel/qcore_unix_p.h
2d2b1a
@@ -66,6 +66,12 @@
2d2b1a
 #  include <ioLib.h>
2d2b1a
 #endif
2d2b1a
2d2b1a
+#ifdef QT_NO_NATIVE_POLL
2d2b1a
+#  include "qpoll_p.h"
2d2b1a
+#else
2d2b1a
+#  include <poll.h>
2d2b1a
+#endif
2d2b1a
+
2d2b1a
 struct sockaddr;
2d2b1a
2d2b1a
 #define EINTR_LOOP(var, cmd)                    \
2d2b1a
@@ -122,6 +128,14 @@ inline timespec operator*(const timespec &t1, int mul)
2d2b1a
     return normalizedTimespec(tmp);
2d2b1a
 }
2d2b1a
2d2b1a
+inline timeval timespecToTimeval(const timespec &ts)
2d2b1a
+{
2d2b1a
+    timeval tv;
2d2b1a
+    tv.tv_sec = ts.tv_sec;
2d2b1a
+    tv.tv_usec = ts.tv_nsec / 1000;
2d2b1a
+    return tv;
2d2b1a
+}
2d2b1a
+
2d2b1a
 inline void qt_ignore_sigpipe()
2d2b1a
 {
2d2b1a
     // Set to ignore SIGPIPE once only.
2d2b1a
@@ -303,6 +317,27 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
2d2b1a
 timespec qt_gettime() Q_DECL_NOTHROW;
2d2b1a
 void qt_nanosleep(timespec amount);
2d2b1a
2d2b1a
+Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
2d2b1a
+
2d2b1a
+static inline int qt_poll_msecs(struct pollfd *fds, nfds_t nfds, int timeout)
2d2b1a
+{
2d2b1a
+    timespec ts, *pts = Q_NULLPTR;
2d2b1a
+
2d2b1a
+    if (timeout >= 0) {
2d2b1a
+        ts.tv_sec = timeout / 1000;
2d2b1a
+        ts.tv_nsec = (timeout % 1000) * 1000 * 1000;
2d2b1a
+        pts = &ts;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    return qt_safe_poll(fds, nfds, pts);
2d2b1a
+}
2d2b1a
+
2d2b1a
+static inline struct pollfd qt_make_pollfd(int fd, short events)
2d2b1a
+{
2d2b1a
+    struct pollfd pfd = { fd, events, 0 };
2d2b1a
+    return pfd;
2d2b1a
+}
2d2b1a
+
2d2b1a
 Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
2d2b1a
                                  const struct timespec *tv);
2d2b1a
2d2b1a
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
2d2b1a
index 155f7b7..7d23283 100644
2d2b1a
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
2d2b1a
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
2d2b1a
@@ -59,7 +59,7 @@
2d2b1a
 #    define _POSIX_MONOTONIC_CLOCK 1
2d2b1a
 #  endif
2d2b1a
 #  include <pipeDrv.h>
2d2b1a
-#  include <selectLib.h>
2d2b1a
+#  include <sys/time.h>
2d2b1a
 #endif
2d2b1a
2d2b1a
 #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
2d2b1a
@@ -68,6 +68,20 @@
2d2b1a
2d2b1a
 QT_BEGIN_NAMESPACE
2d2b1a
2d2b1a
+static const char *socketType(QSocketNotifier::Type type)
2d2b1a
+{
2d2b1a
+    switch (type) {
2d2b1a
+    case QSocketNotifier::Read:
2d2b1a
+        return "Read";
2d2b1a
+    case QSocketNotifier::Write:
2d2b1a
+        return "Write";
2d2b1a
+    case QSocketNotifier::Exception:
2d2b1a
+        return "Exception";
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    Q_UNREACHABLE();
2d2b1a
+}
2d2b1a
+
2d2b1a
 #if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS)
2d2b1a
 static void initThreadPipeFD(int fd)
2d2b1a
 {
2d2b1a
@@ -137,8 +151,6 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
2d2b1a
2d2b1a
     if (pipefail)
2d2b1a
         qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
2d2b1a
-
2d2b1a
-    sn_highest = -1;
2d2b1a
 }
2d2b1a
2d2b1a
 QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
2d2b1a
@@ -163,116 +175,11 @@ QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
2d2b1a
     qDeleteAll(timerList);
2d2b1a
 }
2d2b1a
2d2b1a
-int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout)
2d2b1a
-{
2d2b1a
-    Q_Q(QEventDispatcherUNIX);
2d2b1a
-
2d2b1a
-    // needed in QEventDispatcherUNIX::select()
2d2b1a
-    timerList.updateCurrentTime();
2d2b1a
-
2d2b1a
-    int nsel;
2d2b1a
-    do {
2d2b1a
-        // Process timers and socket notifiers - the common UNIX stuff
2d2b1a
-        int highest = 0;
2d2b1a
-        if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {
2d2b1a
-            // return the highest fd we can wait for input on
2d2b1a
-                sn_vec[0].select_fds = sn_vec[0].enabled_fds;
2d2b1a
-                sn_vec[1].select_fds = sn_vec[1].enabled_fds;
2d2b1a
-                sn_vec[2].select_fds = sn_vec[2].enabled_fds;
2d2b1a
-            highest = sn_highest;
2d2b1a
-        } else {
2d2b1a
-            FD_ZERO(&sn_vec[0].select_fds);
2d2b1a
-            FD_ZERO(&sn_vec[1].select_fds);
2d2b1a
-            FD_ZERO(&sn_vec[2].select_fds);
2d2b1a
-        }
2d2b1a
-
2d2b1a
-        int wakeUpFd = initThreadWakeUp();
2d2b1a
-        highest = qMax(highest, wakeUpFd);
2d2b1a
-
2d2b1a
-        nsel = q->select(highest + 1,
2d2b1a
-                         &sn_vec[0].select_fds,
2d2b1a
-                         &sn_vec[1].select_fds,
2d2b1a
-                         &sn_vec[2].select_fds,
2d2b1a
-                         timeout);
2d2b1a
-    } while (nsel == -1 && (errno == EINTR || errno == EAGAIN));
2d2b1a
-
2d2b1a
-    if (nsel == -1) {
2d2b1a
-        if (errno == EBADF) {
2d2b1a
-            // it seems a socket notifier has a bad fd... find out
2d2b1a
-            // which one it is and disable it
2d2b1a
-            fd_set fdset;
2d2b1a
-            timeval tm;
2d2b1a
-            tm.tv_sec = tm.tv_usec = 0l;
2d2b1a
-
2d2b1a
-            for (int type = 0; type < 3; ++type) {
2d2b1a
-                QSockNotType::List &list = sn_vec[type].list;
2d2b1a
-                if (list.size() == 0)
2d2b1a
-                    continue;
2d2b1a
-
2d2b1a
-                for (int i = 0; i < list.size(); ++i) {
2d2b1a
-                    QSockNot *sn = list[i];
2d2b1a
-
2d2b1a
-                    FD_ZERO(&fdset);
2d2b1a
-                    FD_SET(sn->fd, &fdset);
2d2b1a
-
2d2b1a
-                    int ret = -1;
2d2b1a
-                    do {
2d2b1a
-                        switch (type) {
2d2b1a
-                        case 0: // read
2d2b1a
-                            ret = select(sn->fd + 1, &fdset, 0, 0, &tm;;
2d2b1a
-                            break;
2d2b1a
-                        case 1: // write
2d2b1a
-                            ret = select(sn->fd + 1, 0, &fdset, 0, &tm;;
2d2b1a
-                            break;
2d2b1a
-                        case 2: // except
2d2b1a
-                            ret = select(sn->fd + 1, 0, 0, &fdset, &tm;;
2d2b1a
-                            break;
2d2b1a
-                        }
2d2b1a
-                    } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
2d2b1a
-
2d2b1a
-                    if (ret == -1 && errno == EBADF) {
2d2b1a
-                        // disable the invalid socket notifier
2d2b1a
-                        static const char *t[] = { "Read", "Write", "Exception" };
2d2b1a
-                        qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
2d2b1a
-                                 sn->fd, t[type]);
2d2b1a
-                        sn->obj->setEnabled(false);
2d2b1a
-                    }
2d2b1a
-                }
2d2b1a
-            }
2d2b1a
-        } else {
2d2b1a
-            // EINVAL... shouldn't happen, so let's complain to stderr
2d2b1a
-            // and hope someone sends us a bug report
2d2b1a
-            perror("select");
2d2b1a
-        }
2d2b1a
-    }
2d2b1a
-
2d2b1a
-    int nevents = processThreadWakeUp(nsel);
2d2b1a
-
2d2b1a
-    // activate socket notifiers
2d2b1a
-    if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) {
2d2b1a
-        // if select says data is ready on any socket, then set the socket notifier
2d2b1a
-        // to pending
2d2b1a
-        for (int i=0; i<3; i++) {
2d2b1a
-            QSockNotType::List &list = sn_vec[i].list;
2d2b1a
-            for (int j = 0; j < list.size(); ++j) {
2d2b1a
-                QSockNot *sn = list[j];
2d2b1a
-                if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))
2d2b1a
-                    q->setSocketNotifierPending(sn->obj);
2d2b1a
-            }
2d2b1a
-        }
2d2b1a
-    }
2d2b1a
-    return (nevents + q->activateSocketNotifiers());
2d2b1a
-}
2d2b1a
-
2d2b1a
-int QEventDispatcherUNIXPrivate::initThreadWakeUp()
2d2b1a
+int QEventDispatcherUNIXPrivate::processThreadWakeUp(const pollfd &pfd)
2d2b1a
 {
2d2b1a
-    FD_SET(thread_pipe[0], &sn_vec[0].select_fds);
2d2b1a
-    return thread_pipe[0];
2d2b1a
-}
2d2b1a
+    Q_ASSERT(pfd.fd == thread_pipe[0]);
2d2b1a
2d2b1a
-int QEventDispatcherUNIXPrivate::processThreadWakeUp(int nsel)
2d2b1a
-{
2d2b1a
-    if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) {
2d2b1a
+    if (pfd.revents & POLLIN) {
2d2b1a
         // some other thread woke us up... consume the data on the thread pipe so that
2d2b1a
         // select doesn't immediately return next time
2d2b1a
 #if defined(Q_OS_VXWORKS)
2d2b1a
@@ -302,6 +209,80 @@ int QEventDispatcherUNIXPrivate::processThreadWakeUp(int nsel)
2d2b1a
     return 0;
2d2b1a
 }
2d2b1a
2d2b1a
+void QEventDispatcherUNIXPrivate::setSocketNotifierPending(QSocketNotifier *notifier)
2d2b1a
+{
2d2b1a
+    Q_ASSERT(notifier);
2d2b1a
+
2d2b1a
+    if (pendingNotifiers.contains(notifier))
2d2b1a
+        return;
2d2b1a
+
2d2b1a
+    pendingNotifiers << notifier;
2d2b1a
+}
2d2b1a
+
2d2b1a
+int QEventDispatcherUNIXPrivate::activateTimers()
2d2b1a
+{
2d2b1a
+    return timerList.activateTimers();
2d2b1a
+}
2d2b1a
+
2d2b1a
+void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers()
2d2b1a
+{
2d2b1a
+    foreach (const pollfd &pfd, pollfds) {
2d2b1a
+        if (pfd.fd < 0 || pfd.revents == 0)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        auto it = socketNotifiers.find(pfd.fd);
2d2b1a
+        Q_ASSERT(it != socketNotifiers.end());
2d2b1a
+
2d2b1a
+        const QSocketNotifierSetUNIX &sn_set = it.value();
2d2b1a
+
2d2b1a
+        static const struct {
2d2b1a
+            QSocketNotifier::Type type;
2d2b1a
+            short flags;
2d2b1a
+        } notifiers[] = {
2d2b1a
+            { QSocketNotifier::Read,      POLLIN  | POLLHUP | POLLERR },
2d2b1a
+            { QSocketNotifier::Write,     POLLOUT | POLLHUP | POLLERR },
2d2b1a
+            { QSocketNotifier::Exception, POLLPRI | POLLHUP | POLLERR }
2d2b1a
+        };
2d2b1a
+
2d2b1a
+        for (const auto &n : notifiers) {
2d2b1a
+            QSocketNotifier *notifier = sn_set.notifiers[n.type];
2d2b1a
+
2d2b1a
+            if (!notifier)
2d2b1a
+                continue;
2d2b1a
+
2d2b1a
+            if (pfd.revents & POLLNVAL) {
2d2b1a
+                qWarning("QSocketNotifier: Invalid socket %d with type %s, disabling...",
2d2b1a
+                         it.key(), socketType(n.type));
2d2b1a
+                notifier->setEnabled(false);
2d2b1a
+            }
2d2b1a
+
2d2b1a
+            if (pfd.revents & n.flags)
2d2b1a
+                setSocketNotifierPending(notifier);
2d2b1a
+        }
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    pollfds.resize(0);
2d2b1a
+}
2d2b1a
+
2d2b1a
+int QEventDispatcherUNIXPrivate::activateSocketNotifiers()
2d2b1a
+{
2d2b1a
+    markPendingSocketNotifiers();
2d2b1a
+
2d2b1a
+    if (pendingNotifiers.isEmpty())
2d2b1a
+        return 0;
2d2b1a
+
2d2b1a
+    int n_activated = 0;
2d2b1a
+    QEvent event(QEvent::SockAct);
2d2b1a
+
2d2b1a
+    while (!pendingNotifiers.isEmpty()) {
2d2b1a
+        QSocketNotifier *notifier = pendingNotifiers.takeFirst();
2d2b1a
+        QCoreApplication::sendEvent(notifier, &event);
2d2b1a
+        ++n_activated;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    return n_activated;
2d2b1a
+}
2d2b1a
+
2d2b1a
 QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
2d2b1a
     : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
2d2b1a
 { }
2d2b1a
@@ -311,14 +292,7 @@ QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObj
2d2b1a
 { }
2d2b1a
2d2b1a
 QEventDispatcherUNIX::~QEventDispatcherUNIX()
2d2b1a
-{
2d2b1a
-}
2d2b1a
-
2d2b1a
-int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2d2b1a
-                                 timespec *timeout)
2d2b1a
-{
2d2b1a
-    return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);
2d2b1a
-}
2d2b1a
+{ }
2d2b1a
2d2b1a
 /*!
2d2b1a
     \internal
2d2b1a
@@ -390,22 +364,6 @@ QEventDispatcherUNIX::registeredTimers(QObject *object) const
2d2b1a
 }
2d2b1a
2d2b1a
 /*****************************************************************************
2d2b1a
- Socket notifier type
2d2b1a
- *****************************************************************************/
2d2b1a
-QSockNotType::QSockNotType()
2d2b1a
-{
2d2b1a
-    FD_ZERO(&select_fds);
2d2b1a
-    FD_ZERO(&enabled_fds);
2d2b1a
-    FD_ZERO(&pending_fds);
2d2b1a
-}
2d2b1a
-
2d2b1a
-QSockNotType::~QSockNotType()
2d2b1a
-{
2d2b1a
-    for (int i = 0; i < list.size(); ++i)
2d2b1a
-        delete list[i];
2d2b1a
-}
2d2b1a
-
2d2b1a
-/*****************************************************************************
2d2b1a
  QEventDispatcher implementations for UNIX
2d2b1a
  *****************************************************************************/
2d2b1a
2d2b1a
@@ -413,160 +371,57 @@ void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier)
2d2b1a
 {
2d2b1a
     Q_ASSERT(notifier);
2d2b1a
     int sockfd = notifier->socket();
2d2b1a
-    int type = notifier->type();
2d2b1a
+    QSocketNotifier::Type type = notifier->type();
2d2b1a
 #ifndef QT_NO_DEBUG
2d2b1a
-    if (sockfd < 0
2d2b1a
-        || unsigned(sockfd) >= FD_SETSIZE) {
2d2b1a
-        qWarning("QSocketNotifier: Internal error");
2d2b1a
-        return;
2d2b1a
-    } else if (notifier->thread() != thread()
2d2b1a
-               || thread() != QThread::currentThread()) {
2d2b1a
+    if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
2d2b1a
         qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
2d2b1a
         return;
2d2b1a
     }
2d2b1a
 #endif
2d2b1a
2d2b1a
     Q_D(QEventDispatcherUNIX);
2d2b1a
-    QSockNotType::List &list = d->sn_vec[type].list;
2d2b1a
-    fd_set *fds  = &d->sn_vec[type].enabled_fds;
2d2b1a
-    QSockNot *sn;
2d2b1a
-
2d2b1a
-    sn = new QSockNot;
2d2b1a
-    sn->obj = notifier;
2d2b1a
-    sn->fd = sockfd;
2d2b1a
-    sn->queue = &d->sn_vec[type].pending_fds;
2d2b1a
-
2d2b1a
-    int i;
2d2b1a
-    for (i = 0; i < list.size(); ++i) {
2d2b1a
-        QSockNot *p = list[i];
2d2b1a
-        if (p->fd < sockfd)
2d2b1a
-            break;
2d2b1a
-        if (p->fd == sockfd) {
2d2b1a
-            static const char *t[] = { "Read", "Write", "Exception" };
2d2b1a
-            qWarning("QSocketNotifier: Multiple socket notifiers for "
2d2b1a
-                      "same socket %d and type %s", sockfd, t[type]);
2d2b1a
-        }
2d2b1a
-    }
2d2b1a
-    list.insert(i, sn);
2d2b1a
+    QSocketNotifierSetUNIX &sn_set = d->socketNotifiers[sockfd];
2d2b1a
+
2d2b1a
+    if (sn_set.notifiers[type] && sn_set.notifiers[type] != notifier)
2d2b1a
+        qWarning("%s: Multiple socket notifiers for same socket %d and type %s",
2d2b1a
+                 Q_FUNC_INFO, sockfd, socketType(type));
2d2b1a
2d2b1a
-    FD_SET(sockfd, fds);
2d2b1a
-    d->sn_highest = qMax(d->sn_highest, sockfd);
2d2b1a
+    sn_set.notifiers[type] = notifier;
2d2b1a
 }
2d2b1a
2d2b1a
 void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
2d2b1a
 {
2d2b1a
     Q_ASSERT(notifier);
2d2b1a
     int sockfd = notifier->socket();
2d2b1a
-    int type = notifier->type();
2d2b1a
+    QSocketNotifier::Type type = notifier->type();
2d2b1a
 #ifndef QT_NO_DEBUG
2d2b1a
-    if (sockfd < 0
2d2b1a
-        || unsigned(sockfd) >= FD_SETSIZE) {
2d2b1a
-        qWarning("QSocketNotifier: Internal error");
2d2b1a
-        return;
2d2b1a
-    } else if (notifier->thread() != thread()
2d2b1a
-               || thread() != QThread::currentThread()) {
2d2b1a
+    if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
2d2b1a
         qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
2d2b1a
         return;
2d2b1a
     }
2d2b1a
 #endif
2d2b1a
2d2b1a
     Q_D(QEventDispatcherUNIX);
2d2b1a
-    QSockNotType::List &list = d->sn_vec[type].list;
2d2b1a
-    fd_set *fds  =  &d->sn_vec[type].enabled_fds;
2d2b1a
-    QSockNot *sn = 0;
2d2b1a
-    int i;
2d2b1a
-    for (i = 0; i < list.size(); ++i) {
2d2b1a
-        sn = list[i];
2d2b1a
-        if(sn->obj == notifier && sn->fd == sockfd)
2d2b1a
-            break;
2d2b1a
-    }
2d2b1a
-    if (i == list.size()) // not found
2d2b1a
-        return;
2d2b1a
+    d->pendingNotifiers.removeOne(notifier);
2d2b1a
2d2b1a
-    FD_CLR(sockfd, fds);                        // clear fd bit
2d2b1a
-    FD_CLR(sockfd, sn->queue);
2d2b1a
-    d->sn_pending_list.removeAll(sn);                // remove from activation list
2d2b1a
-    list.removeAt(i);                                // remove notifier found above
2d2b1a
-    delete sn;
2d2b1a
-
2d2b1a
-    if (d->sn_highest == sockfd) {                // find highest fd
2d2b1a
-        d->sn_highest = -1;
2d2b1a
-        for (int i=0; i<3; i++) {
2d2b1a
-            if (!d->sn_vec[i].list.isEmpty())
2d2b1a
-                d->sn_highest = qMax(d->sn_highest,  // list is fd-sorted
2d2b1a
-                                     d->sn_vec[i].list[0]->fd);
2d2b1a
-        }
2d2b1a
-    }
2d2b1a
-}
2d2b1a
-
2d2b1a
-void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier)
2d2b1a
-{
2d2b1a
-    Q_ASSERT(notifier);
2d2b1a
-    int sockfd = notifier->socket();
2d2b1a
-    int type = notifier->type();
2d2b1a
-#ifndef QT_NO_DEBUG
2d2b1a
-    if (sockfd < 0
2d2b1a
-        || unsigned(sockfd) >= FD_SETSIZE) {
2d2b1a
-        qWarning("QSocketNotifier: Internal error");
2d2b1a
+    auto i = d->socketNotifiers.find(sockfd);
2d2b1a
+    if (i == d->socketNotifiers.end())
2d2b1a
         return;
2d2b1a
-    }
2d2b1a
-    Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread());
2d2b1a
-#endif
2d2b1a
+    QSocketNotifierSetUNIX &sn_set = i.value();
2d2b1a
2d2b1a
-    Q_D(QEventDispatcherUNIX);
2d2b1a
-    QSockNotType::List &list = d->sn_vec[type].list;
2d2b1a
-    QSockNot *sn = 0;
2d2b1a
-    int i;
2d2b1a
-    for (i = 0; i < list.size(); ++i) {
2d2b1a
-        sn = list[i];
2d2b1a
-        if(sn->obj == notifier && sn->fd == sockfd)
2d2b1a
-            break;
2d2b1a
-    }
2d2b1a
-    if (i == list.size()) // not found
2d2b1a
+    if (sn_set.notifiers[type] == nullptr)
2d2b1a
         return;
2d2b1a
2d2b1a
-    // We choose a random activation order to be more fair under high load.
2d2b1a
-    // If a constant order is used and a peer early in the list can
2d2b1a
-    // saturate the IO, it might grab our attention completely.
2d2b1a
-    // Also, if we're using a straight list, the callback routines may
2d2b1a
-    // delete other entries from the list before those other entries are
2d2b1a
-    // processed.
2d2b1a
-    if (! FD_ISSET(sn->fd, sn->queue)) {
2d2b1a
-        if (d->sn_pending_list.isEmpty()) {
2d2b1a
-            d->sn_pending_list.append(sn);
2d2b1a
-        } else {
2d2b1a
-            d->sn_pending_list.insert((qrand() & 0xff) %
2d2b1a
-                                      (d->sn_pending_list.size()+1), sn);
2d2b1a
-        }
2d2b1a
-        FD_SET(sn->fd, sn->queue);
2d2b1a
+    if (sn_set.notifiers[type] != notifier) {
2d2b1a
+        qWarning("%s: Multiple socket notifiers for same socket %d and type %s",
2d2b1a
+                 Q_FUNC_INFO, sockfd, socketType(type));
2d2b1a
+        return;
2d2b1a
     }
2d2b1a
-}
2d2b1a
-
2d2b1a
-int QEventDispatcherUNIX::activateTimers()
2d2b1a
-{
2d2b1a
-    Q_ASSERT(thread() == QThread::currentThread());
2d2b1a
-    Q_D(QEventDispatcherUNIX);
2d2b1a
-    return d->timerList.activateTimers();
2d2b1a
-}
2d2b1a
2d2b1a
-int QEventDispatcherUNIX::activateSocketNotifiers()
2d2b1a
-{
2d2b1a
-    Q_D(QEventDispatcherUNIX);
2d2b1a
-    if (d->sn_pending_list.isEmpty())
2d2b1a
-        return 0;
2d2b1a
+    sn_set.notifiers[type] = nullptr;
2d2b1a
2d2b1a
-    // activate entries
2d2b1a
-    int n_act = 0;
2d2b1a
-    QEvent event(QEvent::SockAct);
2d2b1a
-    while (!d->sn_pending_list.isEmpty()) {
2d2b1a
-        QSockNot *sn = d->sn_pending_list.takeFirst();
2d2b1a
-        if (FD_ISSET(sn->fd, sn->queue)) {
2d2b1a
-            FD_CLR(sn->fd, sn->queue);
2d2b1a
-            QCoreApplication::sendEvent(sn->obj, &event);
2d2b1a
-            ++n_act;
2d2b1a
-        }
2d2b1a
-    }
2d2b1a
-    return n_act;
2d2b1a
+    if (sn_set.isEmpty())
2d2b1a
+        d->socketNotifiers.erase(i);
2d2b1a
 }
2d2b1a
2d2b1a
 bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
2d2b1a
@@ -578,39 +433,54 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
2d2b1a
     emit awake();
2d2b1a
     QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
2d2b1a
2d2b1a
-    int nevents = 0;
2d2b1a
+    const bool include_timers = (flags & QEventLoop::X11ExcludeTimers) == 0;
2d2b1a
+    const bool include_notifiers = (flags & QEventLoop::ExcludeSocketNotifiers) == 0;
2d2b1a
+    const bool wait_for_events = flags & QEventLoop::WaitForMoreEvents;
2d2b1a
+
2d2b1a
     const bool canWait = (d->threadData->canWaitLocked()
2d2b1a
                           && !d->interrupt.load()
2d2b1a
-                          && (flags & QEventLoop::WaitForMoreEvents));
2d2b1a
+                          && wait_for_events);
2d2b1a
2d2b1a
     if (canWait)
2d2b1a
         emit aboutToBlock();
2d2b1a
2d2b1a
-    if (!d->interrupt.load()) {
2d2b1a
-        // return the maximum time we can wait for an event.
2d2b1a
-        timespec *tm = 0;
2d2b1a
-        timespec wait_tm = { 0l, 0l };
2d2b1a
-        if (!(flags & QEventLoop::X11ExcludeTimers)) {
2d2b1a
-            if (d->timerList.timerWait(wait_tm))
2d2b1a
-                tm = &wait_tm;
2d2b1a
-        }
2d2b1a
+    if (d->interrupt.load())
2d2b1a
+        return false;
2d2b1a
2d2b1a
-        if (!canWait) {
2d2b1a
-            if (!tm)
2d2b1a
-                tm = &wait_tm;
2d2b1a
+    timespec *tm = nullptr;
2d2b1a
+    timespec wait_tm = { 0, 0 };
2d2b1a
2d2b1a
-            // no time to wait
2d2b1a
-            tm->tv_sec  = 0l;
2d2b1a
-            tm->tv_nsec = 0l;
2d2b1a
-        }
2d2b1a
+    if (!canWait || (include_timers && d->timerList.timerWait(wait_tm)))
2d2b1a
+        tm = &wait_tm;
2d2b1a
2d2b1a
-        nevents = d->doSelect(flags, tm);
2d2b1a
+    d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0));
2d2b1a
+    d->pollfds.resize(0);
2d2b1a
2d2b1a
-        // activate timers
2d2b1a
-        if (! (flags & QEventLoop::X11ExcludeTimers)) {
2d2b1a
-            nevents += activateTimers();
2d2b1a
-        }
2d2b1a
+    if (include_notifiers)
2d2b1a
+        for (auto it = d->socketNotifiers.cbegin(); it != d->socketNotifiers.cend(); ++it)
2d2b1a
+            d->pollfds.append(qt_make_pollfd(it.key(), it.value().events()));
2d2b1a
+
2d2b1a
+    // This must be last, as it's popped off the end below
2d2b1a
+    d->pollfds.append(qt_make_pollfd(d->thread_pipe[0], POLLIN));
2d2b1a
+
2d2b1a
+    int nevents = 0;
2d2b1a
+
2d2b1a
+    switch (qt_safe_poll(d->pollfds.data(), d->pollfds.size(), tm)) {
2d2b1a
+    case -1:
2d2b1a
+        perror("qt_safe_poll");
2d2b1a
+        break;
2d2b1a
+    case 0:
2d2b1a
+        break;
2d2b1a
+    default:
2d2b1a
+        nevents += d->processThreadWakeUp(d->pollfds.takeLast());
2d2b1a
+        if (include_notifiers)
2d2b1a
+            nevents += d->activateSocketNotifiers();
2d2b1a
+        break;
2d2b1a
     }
2d2b1a
+
2d2b1a
+    if (include_timers)
2d2b1a
+        nevents += d->activateTimers();
2d2b1a
+
2d2b1a
     // return true if we handled events, false otherwise
2d2b1a
     return (nevents > 0);
2d2b1a
 }
2d2b1a
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
2d2b1a
index df08080..b76bb8e 100644
2d2b1a
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
2d2b1a
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
2d2b1a
@@ -53,38 +53,21 @@
2d2b1a
 #include "QtCore/qvarlengtharray.h"
2d2b1a
 #include "private/qtimerinfo_unix_p.h"
2d2b1a
2d2b1a
-#if !defined(Q_OS_VXWORKS)
2d2b1a
-#  include <sys/time.h>
2d2b1a
-#  if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL)
2d2b1a
-#    include <sys/select.h>
2d2b1a
-#  endif
2d2b1a
-#endif
2d2b1a
-
2d2b1a
 QT_BEGIN_NAMESPACE
2d2b1a
2d2b1a
-struct QSockNot
2d2b1a
-{
2d2b1a
-    QSocketNotifier *obj;
2d2b1a
-    int fd;
2d2b1a
-    fd_set *queue;
2d2b1a
-};
2d2b1a
+class QEventDispatcherUNIXPrivate;
2d2b1a
2d2b1a
-class QSockNotType
2d2b1a
+struct Q_CORE_EXPORT QSocketNotifierSetUNIX Q_DECL_FINAL
2d2b1a
 {
2d2b1a
-public:
2d2b1a
-    QSockNotType();
2d2b1a
-    ~QSockNotType();
2d2b1a
+    inline QSocketNotifierSetUNIX() Q_DECL_NOTHROW;
2d2b1a
2d2b1a
-    typedef QPodList<QSockNot*, 32> List;
2d2b1a
-
2d2b1a
-    List list;
2d2b1a
-    fd_set select_fds;
2d2b1a
-    fd_set enabled_fds;
2d2b1a
-    fd_set pending_fds;
2d2b1a
+    inline bool isEmpty() const Q_DECL_NOTHROW;
2d2b1a
+    inline short events() const Q_DECL_NOTHROW;
2d2b1a
2d2b1a
+    QSocketNotifier *notifiers[3];
2d2b1a
 };
2d2b1a
2d2b1a
-class QEventDispatcherUNIXPrivate;
2d2b1a
+Q_DECLARE_TYPEINFO(QSocketNotifierSetUNIX, Q_PRIMITIVE_TYPE);
2d2b1a
2d2b1a
 #ifdef Q_OS_QNX
2d2b1a
 #  define FINAL_EXCEPT_BLACKBERRY
2d2b1a
@@ -120,15 +103,6 @@ public:
2d2b1a
2d2b1a
 protected:
2d2b1a
     QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0);
2d2b1a
-
2d2b1a
-    void setSocketNotifierPending(QSocketNotifier *notifier);
2d2b1a
-
2d2b1a
-    int activateTimers();
2d2b1a
-    int activateSocketNotifiers();
2d2b1a
-
2d2b1a
-    virtual int select(int nfds,
2d2b1a
-                       fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2d2b1a
-                       timespec *timeout);
2d2b1a
 };
2d2b1a
2d2b1a
 class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
2d2b1a
@@ -139,9 +113,13 @@ public:
2d2b1a
     QEventDispatcherUNIXPrivate();
2d2b1a
     ~QEventDispatcherUNIXPrivate();
2d2b1a
2d2b1a
-    int doSelect(QEventLoop::ProcessEventsFlags flags, timespec *timeout);
2d2b1a
-    virtual int initThreadWakeUp() FINAL_EXCEPT_BLACKBERRY;
2d2b1a
-    virtual int processThreadWakeUp(int nsel) FINAL_EXCEPT_BLACKBERRY;
2d2b1a
+    int processThreadWakeUp(const pollfd &pfd;;
2d2b1a
+
2d2b1a
+    int activateTimers();
2d2b1a
+
2d2b1a
+    void markPendingSocketNotifiers();
2d2b1a
+    int activateSocketNotifiers();
2d2b1a
+    void setSocketNotifierPending(QSocketNotifier *notifier);
2d2b1a
2d2b1a
     bool mainThread;
2d2b1a
2d2b1a
@@ -149,15 +127,12 @@ public:
2d2b1a
     // if thread_pipe[1] is -1, then eventfd(7) is in use and is stored in thread_pipe[0]
2d2b1a
     int thread_pipe[2];
2d2b1a
2d2b1a
-    // highest fd for all socket notifiers
2d2b1a
-    int sn_highest;
2d2b1a
-    // 3 socket notifier types - read, write and exception
2d2b1a
-    QSockNotType sn_vec[3];
2d2b1a
+    QVector<pollfd> pollfds;
2d2b1a
2d2b1a
-    QTimerInfoList timerList;
2d2b1a
+    QHash<int, QSocketNotifierSetUNIX> socketNotifiers;
2d2b1a
+    QVector<QSocketNotifier *> pendingNotifiers;
2d2b1a
2d2b1a
-    // pending socket notifiers list
2d2b1a
-    QSockNotType::List sn_pending_list;
2d2b1a
+    QTimerInfoList timerList;
2d2b1a
2d2b1a
     QAtomicInt wakeUps;
2d2b1a
     QAtomicInt interrupt; // bool
2d2b1a
@@ -165,6 +140,34 @@ public:
2d2b1a
2d2b1a
 #undef FINAL_EXCEPT_BLACKBERRY
2d2b1a
2d2b1a
+inline QSocketNotifierSetUNIX::QSocketNotifierSetUNIX() Q_DECL_NOTHROW
2d2b1a
+{
2d2b1a
+    notifiers[0] = 0;
2d2b1a
+    notifiers[1] = 0;
2d2b1a
+    notifiers[2] = 0;
2d2b1a
+}
2d2b1a
+
2d2b1a
+inline bool QSocketNotifierSetUNIX::isEmpty() const Q_DECL_NOTHROW
2d2b1a
+{
2d2b1a
+    return !notifiers[0] && !notifiers[1] && !notifiers[2];
2d2b1a
+}
2d2b1a
+
2d2b1a
+inline short QSocketNotifierSetUNIX::events() const Q_DECL_NOTHROW
2d2b1a
+{
2d2b1a
+    short result = 0;
2d2b1a
+
2d2b1a
+    if (notifiers[0])
2d2b1a
+        result |= POLLIN;
2d2b1a
+
2d2b1a
+    if (notifiers[1])
2d2b1a
+        result |= POLLOUT;
2d2b1a
+
2d2b1a
+    if (notifiers[2])
2d2b1a
+        result |= POLLPRI;
2d2b1a
+
2d2b1a
+    return result;
2d2b1a
+}
2d2b1a
+
2d2b1a
 QT_END_NAMESPACE
2d2b1a
2d2b1a
 #endif // QEVENTDISPATCHER_UNIX_P_H
2d2b1a
diff --git a/src/corelib/kernel/qpoll.cpp b/src/corelib/kernel/qpoll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..b152518
2d2b1a
--- /dev/null
2d2b1a
+++ b/src/corelib/kernel/qpoll.cpp
2d2b1a
@@ -0,0 +1,220 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the QtCore module of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#include "qcore_unix_p.h"
2d2b1a
+
2d2b1a
+QT_BEGIN_NAMESPACE
2d2b1a
+
2d2b1a
+#define QT_POLL_READ_MASK   (POLLIN | POLLRDNORM)
2d2b1a
+#define QT_POLL_WRITE_MASK  (POLLOUT | POLLWRNORM | POLLWRBAND)
2d2b1a
+#define QT_POLL_EXCEPT_MASK (POLLPRI | POLLRDBAND)
2d2b1a
+#define QT_POLL_ERROR_MASK  (POLLERR | POLLNVAL)
2d2b1a
+#define QT_POLL_EVENTS_MASK (QT_POLL_READ_MASK | QT_POLL_WRITE_MASK | QT_POLL_EXCEPT_MASK)
2d2b1a
+
2d2b1a
+static inline int qt_poll_prepare(struct pollfd *fds, nfds_t nfds,
2d2b1a
+                                  fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
2d2b1a
+{
2d2b1a
+    int max_fd = -1;
2d2b1a
+
2d2b1a
+    FD_ZERO(read_fds);
2d2b1a
+    FD_ZERO(write_fds);
2d2b1a
+    FD_ZERO(except_fds);
2d2b1a
+
2d2b1a
+    for (nfds_t i = 0; i < nfds; i++) {
2d2b1a
+        if (fds[i].fd >= FD_SETSIZE) {
2d2b1a
+            errno = EINVAL;
2d2b1a
+            return -1;
2d2b1a
+        }
2d2b1a
+
2d2b1a
+        if ((fds[i].fd < 0) || (fds[i].revents & QT_POLL_ERROR_MASK))
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (fds[i].events & QT_POLL_READ_MASK)
2d2b1a
+            FD_SET(fds[i].fd, read_fds);
2d2b1a
+
2d2b1a
+        if (fds[i].events & QT_POLL_WRITE_MASK)
2d2b1a
+            FD_SET(fds[i].fd, write_fds);
2d2b1a
+
2d2b1a
+        if (fds[i].events & QT_POLL_EXCEPT_MASK)
2d2b1a
+            FD_SET(fds[i].fd, except_fds);
2d2b1a
+
2d2b1a
+        if (fds[i].events & QT_POLL_EVENTS_MASK)
2d2b1a
+            max_fd = qMax(max_fd, fds[i].fd);
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    return max_fd + 1;
2d2b1a
+}
2d2b1a
+
2d2b1a
+static inline void qt_poll_examine_ready_read(struct pollfd &pfd)
2d2b1a
+{
2d2b1a
+    int res;
2d2b1a
+    char data;
2d2b1a
+
2d2b1a
+    EINTR_LOOP(res, ::recv(pfd.fd, &data, sizeof(data), MSG_PEEK));
2d2b1a
+    const int error = (res < 0) ? errno : 0;
2d2b1a
+
2d2b1a
+    if (res == 0) {
2d2b1a
+        pfd.revents |= POLLHUP;
2d2b1a
+    } else if (res > 0 || error == ENOTSOCK || error == ENOTCONN) {
2d2b1a
+        pfd.revents |= QT_POLL_READ_MASK & pfd.events;
2d2b1a
+    } else {
2d2b1a
+        switch (error) {
2d2b1a
+        case ESHUTDOWN:
2d2b1a
+        case ECONNRESET:
2d2b1a
+        case ECONNABORTED:
2d2b1a
+        case ENETRESET:
2d2b1a
+            pfd.revents |= POLLHUP;
2d2b1a
+            break;
2d2b1a
+        default:
2d2b1a
+            pfd.revents |= POLLERR;
2d2b1a
+            break;
2d2b1a
+        }
2d2b1a
+    }
2d2b1a
+}
2d2b1a
+
2d2b1a
+static inline int qt_poll_sweep(struct pollfd *fds, nfds_t nfds,
2d2b1a
+                                fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
2d2b1a
+{
2d2b1a
+    int result = 0;
2d2b1a
+
2d2b1a
+    for (nfds_t i = 0; i < nfds; i++) {
2d2b1a
+        if (fds[i].fd < 0)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (FD_ISSET(fds[i].fd, read_fds))
2d2b1a
+            qt_poll_examine_ready_read(fds[i]);
2d2b1a
+
2d2b1a
+        if (FD_ISSET(fds[i].fd, write_fds))
2d2b1a
+            fds[i].revents |= QT_POLL_WRITE_MASK & fds[i].events;
2d2b1a
+
2d2b1a
+        if (FD_ISSET(fds[i].fd, except_fds))
2d2b1a
+            fds[i].revents |= QT_POLL_EXCEPT_MASK & fds[i].events;
2d2b1a
+
2d2b1a
+        if (fds[i].revents != 0)
2d2b1a
+            result++;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    return result;
2d2b1a
+}
2d2b1a
+
2d2b1a
+static inline bool qt_poll_is_bad_fd(int fd)
2d2b1a
+{
2d2b1a
+    int ret;
2d2b1a
+    EINTR_LOOP(ret, fcntl(fd, F_GETFD));
2d2b1a
+    return (ret == -1 && errno == EBADF);
2d2b1a
+}
2d2b1a
+
2d2b1a
+static inline int qt_poll_mark_bad_fds(struct pollfd *fds, const nfds_t nfds)
2d2b1a
+{
2d2b1a
+    int n_marked = 0;
2d2b1a
+
2d2b1a
+    for (nfds_t i = 0; i < nfds; i++) {
2d2b1a
+        if (fds[i].fd < 0)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (fds[i].revents & QT_POLL_ERROR_MASK)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (qt_poll_is_bad_fd(fds[i].fd)) {
2d2b1a
+            fds[i].revents |= POLLNVAL;
2d2b1a
+            n_marked++;
2d2b1a
+        }
2d2b1a
+   }
2d2b1a
+
2d2b1a
+   return n_marked;
2d2b1a
+}
2d2b1a
+
2d2b1a
+int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts)
2d2b1a
+{
2d2b1a
+    if (!fds && nfds) {
2d2b1a
+        errno = EFAULT;
2d2b1a
+        return -1;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    fd_set read_fds, write_fds, except_fds;
2d2b1a
+    struct timeval tv, *ptv = 0;
2d2b1a
+
2d2b1a
+    if (timeout_ts) {
2d2b1a
+        tv = timespecToTimeval(*timeout_ts);
2d2b1a
+        ptv = &tv;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    int n_bad_fds = 0;
2d2b1a
+
2d2b1a
+    for (nfds_t i = 0; i < nfds; i++) {
2d2b1a
+        fds[i].revents = 0;
2d2b1a
+
2d2b1a
+        if (fds[i].fd < 0)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (fds[i].events & QT_POLL_EVENTS_MASK)
2d2b1a
+            continue;
2d2b1a
+
2d2b1a
+        if (qt_poll_is_bad_fd(fds[i].fd)) {
2d2b1a
+            // Mark bad file descriptors that have no event flags set
2d2b1a
+            // here, as we won't be passing them to select below and therefore
2d2b1a
+            // need to do the check ourselves
2d2b1a
+            fds[i].revents = POLLNVAL;
2d2b1a
+            n_bad_fds++;
2d2b1a
+        }
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    forever {
2d2b1a
+        const int max_fd = qt_poll_prepare(fds, nfds, &read_fds, &write_fds, &except_fds);
2d2b1a
+
2d2b1a
+        if (max_fd < 0)
2d2b1a
+            return max_fd;
2d2b1a
+
2d2b1a
+        if (n_bad_fds > 0) {
2d2b1a
+            tv.tv_sec = 0;
2d2b1a
+            tv.tv_usec = 0;
2d2b1a
+            ptv = &tv;
2d2b1a
+        }
2d2b1a
+
2d2b1a
+        const int ret = ::select(max_fd, &read_fds, &write_fds, &except_fds, ptv);
2d2b1a
+
2d2b1a
+        if (ret == 0)
2d2b1a
+            return n_bad_fds;
2d2b1a
+
2d2b1a
+        if (ret > 0)
2d2b1a
+            return qt_poll_sweep(fds, nfds, &read_fds, &write_fds, &except_fds);
2d2b1a
+
2d2b1a
+        if (errno != EBADF)
2d2b1a
+            return -1;
2d2b1a
+
2d2b1a
+        // We have at least one bad file descriptor that we waited on, find out which and try again
2d2b1a
+        n_bad_fds += qt_poll_mark_bad_fds(fds, nfds);
2d2b1a
+    }
2d2b1a
+}
2d2b1a
+
2d2b1a
+QT_END_NAMESPACE
2d2b1a
diff --git a/src/corelib/kernel/qpoll_p.h b/src/corelib/kernel/qpoll_p.h
2d2b1a
new file mode 100644
2d2b1a
index 0000000..497058a
2d2b1a
--- /dev/null
2d2b1a
+++ b/src/corelib/kernel/qpoll_p.h
2d2b1a
@@ -0,0 +1,79 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the QtCore module of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#ifndef QPOLL_P_H
2d2b1a
+#define QPOLL_P_H
2d2b1a
+
2d2b1a
+//
2d2b1a
+//  W A R N I N G
2d2b1a
+//  -------------
2d2b1a
+//
2d2b1a
+// This file is not part of the Qt API.  It exists for the convenience
2d2b1a
+// of Qt code on Unix. This header file may change from version to
2d2b1a
+// version without notice, or even be removed.
2d2b1a
+//
2d2b1a
+// We mean it.
2d2b1a
+//
2d2b1a
+
2d2b1a
+#include <QtCore/qglobal.h>
2d2b1a
+
2d2b1a
+QT_BEGIN_NAMESPACE
2d2b1a
+
2d2b1a
+#ifdef QT_NO_NATIVE_POLL
2d2b1a
+
2d2b1a
+#include <unistd.h>
2d2b1a
+#include <time.h>
2d2b1a
+
2d2b1a
+struct pollfd {
2d2b1a
+   int   fd;
2d2b1a
+   short events, revents;
2d2b1a
+};
2d2b1a
+
2d2b1a
+typedef unsigned long int nfds_t;
2d2b1a
+
2d2b1a
+#define POLLIN     0x001
2d2b1a
+#define POLLPRI    0x002
2d2b1a
+#define POLLOUT    0x004
2d2b1a
+#define POLLERR    0x008
2d2b1a
+#define POLLHUP    0x010
2d2b1a
+#define POLLNVAL   0x020
2d2b1a
+#define POLLRDNORM 0x040
2d2b1a
+#define POLLRDBAND 0x080
2d2b1a
+#define POLLWRNORM 0x100
2d2b1a
+#define POLLWRBAND 0x200
2d2b1a
+
2d2b1a
+#endif // QT_NO_NATIVE_POLL
2d2b1a
+
2d2b1a
+QT_END_NAMESPACE
2d2b1a
+
2d2b1a
+#endif // QPOLL_P_H
2d2b1a
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
2d2b1a
index a356e21..79b9b9c 100644
2d2b1a
--- a/src/network/socket/qlocalserver_unix.cpp
2d2b1a
+++ b/src/network/socket/qlocalserver_unix.cpp
2d2b1a
@@ -277,24 +277,27 @@ void QLocalServerPrivate::_q_onNewConnection()
2d2b1a
2d2b1a
 void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
2d2b1a
 {
2d2b1a
-    fd_set readfds;
2d2b1a
-    FD_ZERO(&readfds);
2d2b1a
-    FD_SET(listenSocket, &readfds);
2d2b1a
+    pollfd pfd = qt_make_pollfd(listenSocket, POLLIN);
2d2b1a
2d2b1a
-    struct timespec timeout;
2d2b1a
-    timeout.tv_sec = msec / 1000;
2d2b1a
-    timeout.tv_nsec = (msec % 1000) * 1000 * 1000;
2d2b1a
+    switch (qt_poll_msecs(&pfd, 1, msec)) {
2d2b1a
+    case 0:
2d2b1a
+        if (timedOut)
2d2b1a
+            *timedOut = true;
2d2b1a
+        return;
2d2b1a
+        break;
2d2b1a
+    default:
2d2b1a
+        if ((pfd.revents & POLLNVAL) == 0) {
2d2b1a
+            _q_onNewConnection();
2d2b1a
+            return;
2d2b1a
+        }
2d2b1a
2d2b1a
-    int result = -1;
2d2b1a
-    result = qt_safe_select(listenSocket + 1, &readfds, 0, 0, (msec == -1) ? 0 : &timeout);
2d2b1a
-    if (-1 == result) {
2d2b1a
+        errno = EBADF;
2d2b1a
+        // FALLTHROUGH
2d2b1a
+    case -1:
2d2b1a
         setError(QLatin1String("QLocalServer::waitForNewConnection"));
2d2b1a
         closeServer();
2d2b1a
+        break;
2d2b1a
     }
2d2b1a
-    if (result > 0)
2d2b1a
-        _q_onNewConnection();
2d2b1a
-    if (timedOut)
2d2b1a
-        *timedOut = (result == 0);
2d2b1a
 }
2d2b1a
2d2b1a
 void QLocalServerPrivate::setError(const QString &function)
2d2b1a
diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp
2d2b1a
index bb0f11f..3e85217 100644
2d2b1a
--- a/src/network/socket/qlocalsocket_unix.cpp
2d2b1a
+++ b/src/network/socket/qlocalsocket_unix.cpp
2d2b1a
@@ -507,36 +507,25 @@ void QLocalSocket::setReadBufferSize(qint64 size)
2d2b1a
 bool QLocalSocket::waitForConnected(int msec)
2d2b1a
 {
2d2b1a
     Q_D(QLocalSocket);
2d2b1a
+
2d2b1a
     if (state() != ConnectingState)
2d2b1a
         return (state() == ConnectedState);
2d2b1a
2d2b1a
-    fd_set fds;
2d2b1a
-    FD_ZERO(&fds);
2d2b1a
-    FD_SET(d->connectingSocket, &fds);
2d2b1a
+    QElapsedTimer timer;
2d2b1a
+    timer.start();
2d2b1a
2d2b1a
-    timeval timeout;
2d2b1a
-    timeout.tv_sec = msec / 1000;
2d2b1a
-    timeout.tv_usec = (msec % 1000) * 1000;
2d2b1a
+    pollfd pfd = qt_make_pollfd(d->connectingSocket, POLLIN);
2d2b1a
2d2b1a
-    // timeout can not be 0 or else select will return an error.
2d2b1a
-    if (0 == msec)
2d2b1a
-        timeout.tv_usec = 1000;
2d2b1a
+    do {
2d2b1a
+        const int timeout = (msec > 0) ? qMax(msec - timer.elapsed(), Q_INT64_C(0)) : msec;
2d2b1a
+        const int result = qt_poll_msecs(&pfd, 1, timeout);
2d2b1a
2d2b1a
-    int result = -1;
2d2b1a
-    // on Linux timeout will be updated by select, but _not_ on other systems.
2d2b1a
-    QElapsedTimer timer;
2d2b1a
-    timer.start();
2d2b1a
-    while (state() == ConnectingState
2d2b1a
-           && (-1 == msec || timer.elapsed() < msec)) {
2d2b1a
-        result = ::select(d->connectingSocket + 1, &fds, 0, 0, &timeout);
2d2b1a
-        if (-1 == result && errno != EINTR) {
2d2b1a
-            d->errorOccurred( QLocalSocket::UnknownSocketError,
2d2b1a
-                    QLatin1String("QLocalSocket::waitForConnected"));
2d2b1a
-            break;
2d2b1a
-        }
2d2b1a
-        if (result > 0)
2d2b1a
+        if (result == -1)
2d2b1a
+            d->errorOccurred(QLocalSocket::UnknownSocketError,
2d2b1a
+                             QLatin1String("QLocalSocket::waitForConnected"));
2d2b1a
+        else if (result > 0)
2d2b1a
             d->_q_connectToSocket();
2d2b1a
-    }
2d2b1a
+    } while (state() == ConnectingState && !timer.hasExpired(msec));
2d2b1a
2d2b1a
     return (state() == ConnectedState);
2d2b1a
 }
2d2b1a
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
2d2b1a
index 6a740f4..de86f27 100644
2d2b1a
--- a/src/network/socket/qnativesocketengine_unix.cpp
2d2b1a
+++ b/src/network/socket/qnativesocketengine_unix.cpp
2d2b1a
@@ -1256,47 +1256,36 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c
2d2b1a
2d2b1a
 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) const
2d2b1a
 {
2d2b1a
-    fd_set fds;
2d2b1a
-    FD_ZERO(&fds);
2d2b1a
-    FD_SET(socketDescriptor, &fds);
2d2b1a
-
2d2b1a
-    struct timespec tv;
2d2b1a
-    tv.tv_sec = timeout / 1000;
2d2b1a
-    tv.tv_nsec = (timeout % 1000) * 1000 * 1000;
2d2b1a
-
2d2b1a
-    int retval;
2d2b1a
-    if (selectForRead)
2d2b1a
-        retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv;;
2d2b1a
-    else
2d2b1a
-        retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv;;
2d2b1a
-
2d2b1a
-    return retval;
2d2b1a
+    bool dummy;
2d2b1a
+    return nativeSelect(timeout, selectForRead, !selectForRead, &dummy, &dummy);
2d2b1a
 }
2d2b1a
2d2b1a
 int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool checkWrite,
2d2b1a
                        bool *selectForRead, bool *selectForWrite) const
2d2b1a
 {
2d2b1a
-    fd_set fdread;
2d2b1a
-    FD_ZERO(&fdread);
2d2b1a
+    pollfd pfd = qt_make_pollfd(socketDescriptor, 0);
2d2b1a
+
2d2b1a
     if (checkRead)
2d2b1a
-        FD_SET(socketDescriptor, &fdread);
2d2b1a
+        pfd.events |= POLLIN;
2d2b1a
2d2b1a
-    fd_set fdwrite;
2d2b1a
-    FD_ZERO(&fdwrite);
2d2b1a
     if (checkWrite)
2d2b1a
-        FD_SET(socketDescriptor, &fdwrite);
2d2b1a
+        pfd.events |= POLLOUT;
2d2b1a
2d2b1a
-    struct timespec tv;
2d2b1a
-    tv.tv_sec = timeout / 1000;
2d2b1a
-    tv.tv_nsec = (timeout % 1000) * 1000 * 1000;
2d2b1a
-
2d2b1a
-    int ret;
2d2b1a
-    ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv;;
2d2b1a
+    const int ret = qt_poll_msecs(&pfd, 1, timeout);
2d2b1a
2d2b1a
     if (ret <= 0)
2d2b1a
         return ret;
2d2b1a
-    *selectForRead = FD_ISSET(socketDescriptor, &fdread);
2d2b1a
-    *selectForWrite = FD_ISSET(socketDescriptor, &fdwrite);
2d2b1a
+
2d2b1a
+    if (pfd.revents & POLLNVAL) {
2d2b1a
+        errno = EBADF;
2d2b1a
+        return -1;
2d2b1a
+    }
2d2b1a
+
2d2b1a
+    static const short read_flags = POLLIN | POLLHUP | POLLERR;
2d2b1a
+    static const short write_flags = POLLOUT | POLLERR;
2d2b1a
+
2d2b1a
+    *selectForRead = ((pfd.revents & read_flags) != 0);
2d2b1a
+    *selectForWrite = ((pfd.revents & write_flags) != 0);
2d2b1a
2d2b1a
     return ret;
2d2b1a
 }
2d2b1a
diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
2d2b1a
index 8ffe4d8..c528891 100644
2d2b1a
--- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
2d2b1a
+++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp
2d2b1a
@@ -48,6 +48,7 @@ private slots:
2d2b1a
     void memberFunctions();
2d2b1a
     void implicitConvertibleTypes();
2d2b1a
     void runWaitLoop();
2d2b1a
+    void pollForIsFinished();
2d2b1a
     void recursive();
2d2b1a
 #ifndef QT_NO_EXCEPTIONS
2d2b1a
     void exceptions();
2d2b1a
@@ -353,6 +354,33 @@ void tst_QtConcurrentRun::runWaitLoop()
2d2b1a
         run(fn).waitForFinished();
2d2b1a
 }
2d2b1a
2d2b1a
+static bool allFinished(const QList<QFuture<void> > &futures)
2d2b1a
+{
2d2b1a
+    auto hasNotFinished = [](const QFuture<void> &future) { return !future.isFinished(); };
2d2b1a
+    return std::find_if(futures.cbegin(), futures.cend(), hasNotFinished)
2d2b1a
+        == futures.constEnd();
2d2b1a
+}
2d2b1a
+
2d2b1a
+static void runFunction()
2d2b1a
+{
2d2b1a
+    QEventLoop loop;
2d2b1a
+    QTimer::singleShot(20, &loop, &QEventLoop::quit);
2d2b1a
+    loop.exec();
2d2b1a
+}
2d2b1a
+
2d2b1a
+void tst_QtConcurrentRun::pollForIsFinished()
2d2b1a
+{
2d2b1a
+    const int numThreads = std::max(4, 2 * QThread::idealThreadCount());
2d2b1a
+    QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
2d2b1a
+
2d2b1a
+    QFutureSynchronizer<void> synchronizer;
2d2b1a
+    for (int i = 0; i < numThreads; ++i)
2d2b1a
+        synchronizer.addFuture(QtConcurrent::run(&runFunction));
2d2b1a
+
2d2b1a
+    // same as synchronizer.waitForFinished() but with a timeout
2d2b1a
+    QTRY_VERIFY(allFinished(synchronizer.futures()));
2d2b1a
+}
2d2b1a
+
2d2b1a
 QAtomicInt count;
2d2b1a
2d2b1a
 void recursiveRun(int level)
2d2b1a
diff --git a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
2d2b1a
index c8bb4cd..9b2bada 100644
2d2b1a
--- a/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
2d2b1a
+++ b/tests/auto/corelib/kernel/qeventloop/tst_qeventloop.cpp
2d2b1a
@@ -430,11 +430,8 @@ public slots:
2d2b1a
         dataSent = serverSocket->waitForBytesWritten(-1);
2d2b1a
2d2b1a
         if (dataSent) {
2d2b1a
-            fd_set fdread;
2d2b1a
-            int fd = socket->socketDescriptor();
2d2b1a
-            FD_ZERO(&fdread);
2d2b1a
-            FD_SET(fd, &fdread);
2d2b1a
-            dataReadable = (1 == qt_safe_select(fd + 1, &fdread, 0, 0, 0));
2d2b1a
+            pollfd pfd = qt_make_pollfd(socket->socketDescriptor(), POLLIN);
2d2b1a
+            dataReadable = (1 == qt_safe_poll(&pfd, 1, nullptr));
2d2b1a
         }
2d2b1a
2d2b1a
         if (!dataReadable) {
2d2b1a
diff --git a/tests/manual/qt_poll/qt_poll.pro b/tests/manual/qt_poll/qt_poll.pro
2d2b1a
new file mode 100644
2d2b1a
index 0000000..beea4d1
2d2b1a
--- /dev/null
2d2b1a
+++ b/tests/manual/qt_poll/qt_poll.pro
2d2b1a
@@ -0,0 +1,7 @@
2d2b1a
+CONFIG += testcase
2d2b1a
+TARGET = tst_qt_poll
2d2b1a
+QT = core-private network testlib
2d2b1a
+INCLUDEPATH += ../../../src/corelib/kernel
2d2b1a
+SOURCES += \
2d2b1a
+    tst_qt_poll.cpp \
2d2b1a
+    ../../../src/corelib/kernel/qpoll.cpp
2d2b1a
diff --git a/tests/manual/qt_poll/tst_qt_poll.cpp b/tests/manual/qt_poll/tst_qt_poll.cpp
2d2b1a
new file mode 100644
2d2b1a
index 0000000..56e41e4
2d2b1a
--- /dev/null
2d2b1a
+++ b/tests/manual/qt_poll/tst_qt_poll.cpp
2d2b1a
@@ -0,0 +1,155 @@
2d2b1a
+/****************************************************************************
2d2b1a
+**
2d2b1a
+** Copyright (C) 2015 The Qt Company Ltd.
2d2b1a
+** Contact: http://www.qt.io/licensing/
2d2b1a
+**
2d2b1a
+** This file is part of the test suite of the Qt Toolkit.
2d2b1a
+**
2d2b1a
+** $QT_BEGIN_LICENSE:LGPL21$
2d2b1a
+** Commercial License Usage
2d2b1a
+** Licensees holding valid commercial Qt licenses may use this file in
2d2b1a
+** accordance with the commercial license agreement provided with the
2d2b1a
+** Software or, alternatively, in accordance with the terms contained in
2d2b1a
+** a written agreement between you and The Qt Company. For licensing terms
2d2b1a
+** and conditions see http://www.qt.io/terms-conditions. For further
2d2b1a
+** information use the contact form at http://www.qt.io/contact-us.
2d2b1a
+**
2d2b1a
+** GNU Lesser General Public License Usage
2d2b1a
+** Alternatively, this file may be used under the terms of the GNU Lesser
2d2b1a
+** General Public License version 2.1 or version 3 as published by the Free
2d2b1a
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
2d2b1a
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
2d2b1a
+** following information to ensure the GNU Lesser General Public License
2d2b1a
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
2d2b1a
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
2d2b1a
+**
2d2b1a
+** As a special exception, The Qt Company gives you certain additional
2d2b1a
+** rights. These rights are described in The Qt Company LGPL Exception
2d2b1a
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
2d2b1a
+**
2d2b1a
+** $QT_END_LICENSE$
2d2b1a
+**
2d2b1a
+****************************************************************************/
2d2b1a
+
2d2b1a
+#ifndef QT_NO_NATIVE_POLL
2d2b1a
+#define QT_NO_NATIVE_POLL
2d2b1a
+#endif
2d2b1a
+
2d2b1a
+#include <QtTest/QtTest>
2d2b1a
+#include <QtNetwork>
2d2b1a
+
2d2b1a
+#include <private/qcore_unix_p.h>
2d2b1a
+
2d2b1a
+QT_BEGIN_NAMESPACE
2d2b1a
+// defined in qpoll.cpp
2d2b1a
+int qt_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
2d2b1a
+QT_END_NAMESPACE
2d2b1a
+
2d2b1a
+class tst_qt_poll : public QObject
2d2b1a
+{
2d2b1a
+    Q_OBJECT
2d2b1a
+
2d2b1a
+private slots:
2d2b1a
+    void pollout();
2d2b1a
+    void pollin();
2d2b1a
+    void pollnval();
2d2b1a
+    void pollprihup();
2d2b1a
+};
2d2b1a
+
2d2b1a
+void tst_qt_poll::pollout()
2d2b1a
+{
2d2b1a
+    int fds[2];
2d2b1a
+    QCOMPARE(pipe(fds), 0);
2d2b1a
+
2d2b1a
+    struct pollfd pfd = { fds[1], POLLOUT, 0 };
2d2b1a
+    const int nready = qt_poll(&pfd, 1, NULL);
2d2b1a
+
2d2b1a
+    QCOMPARE(nready, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLOUT));
2d2b1a
+
2d2b1a
+    qt_safe_close(fds[0]);
2d2b1a
+    qt_safe_close(fds[1]);
2d2b1a
+}
2d2b1a
+
2d2b1a
+void tst_qt_poll::pollin()
2d2b1a
+{
2d2b1a
+    int fds[2];
2d2b1a
+    QCOMPARE(pipe(fds), 0);
2d2b1a
+
2d2b1a
+    const char data = 'Q';
2d2b1a
+    QCOMPARE(qt_safe_write(fds[1], &data, 1), 1);
2d2b1a
+
2d2b1a
+    struct pollfd pfd = { fds[0], POLLIN, 0 };
2d2b1a
+    const int nready = qt_poll(&pfd, 1, NULL);
2d2b1a
+
2d2b1a
+    QCOMPARE(nready, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLIN));
2d2b1a
+
2d2b1a
+    qt_safe_close(fds[0]);
2d2b1a
+    qt_safe_close(fds[1]);
2d2b1a
+}
2d2b1a
+
2d2b1a
+void tst_qt_poll::pollnval()
2d2b1a
+{
2d2b1a
+    struct pollfd pfd = { 42, POLLOUT, 0 };
2d2b1a
+
2d2b1a
+    int nready = qt_poll(&pfd, 1, NULL);
2d2b1a
+    QCOMPARE(nready, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLNVAL));
2d2b1a
+
2d2b1a
+    pfd.events = 0;
2d2b1a
+    pfd.revents = 0;
2d2b1a
+
2d2b1a
+    nready = qt_poll(&pfd, 1, NULL);
2d2b1a
+    QCOMPARE(nready, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLNVAL));
2d2b1a
+}
2d2b1a
+
2d2b1a
+void tst_qt_poll::pollprihup()
2d2b1a
+{
2d2b1a
+    QTcpServer server;
2d2b1a
+    QTcpSocket client_socket;
2d2b1a
+
2d2b1a
+    QVERIFY(server.listen(QHostAddress::LocalHost));
2d2b1a
+
2d2b1a
+    const quint16 server_port = server.serverPort();
2d2b1a
+    client_socket.connectToHost(server.serverAddress(), server_port);
2d2b1a
+
2d2b1a
+    QVERIFY(client_socket.waitForConnected());
2d2b1a
+    QVERIFY(server.waitForNewConnection());
2d2b1a
+
2d2b1a
+    QTcpSocket *server_socket = server.nextPendingConnection();
2d2b1a
+    server.close();
2d2b1a
+
2d2b1a
+    // TCP supports only a single byte of urgent data
2d2b1a
+    static const char oob_out = 'Q';
2d2b1a
+    QCOMPARE(::send(server_socket->socketDescriptor(), &oob_out, 1, MSG_OOB),
2d2b1a
+             ssize_t(1));
2d2b1a
+
2d2b1a
+    struct pollfd pfd = {
2d2b1a
+        int(client_socket.socketDescriptor()),
2d2b1a
+        POLLPRI | POLLIN,
2d2b1a
+        0
2d2b1a
+    };
2d2b1a
+    int res = qt_poll(&pfd, 1, NULL);
2d2b1a
+
2d2b1a
+    QCOMPARE(res, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLPRI | POLLIN));
2d2b1a
+
2d2b1a
+    char oob_in = 0;
2d2b1a
+    // We do not specify MSG_OOB here as SO_OOBINLINE is turned on by default
2d2b1a
+    // in the native socket engine
2d2b1a
+    QCOMPARE(::recv(client_socket.socketDescriptor(), &oob_in, 1, 0),
2d2b1a
+             ssize_t(1));
2d2b1a
+    QCOMPARE(oob_in, oob_out);
2d2b1a
+
2d2b1a
+    server_socket->close();
2d2b1a
+    pfd.events = POLLIN;
2d2b1a
+    res = qt_poll(&pfd, 1, NULL);
2d2b1a
+
2d2b1a
+    QCOMPARE(res, 1);
2d2b1a
+    QCOMPARE(pfd.revents, short(POLLHUP));
2d2b1a
+}
2d2b1a
+
2d2b1a
+QTEST_APPLESS_MAIN(tst_qt_poll)
2d2b1a
+#include "tst_qt_poll.moc"
2d2b1a
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
2d2b1a
index 555ccbf..67a581a 100644
2d2b1a
--- a/tools/configure/configureapp.cpp
2d2b1a
+++ b/tools/configure/configureapp.cpp
2d2b1a
@@ -1733,6 +1733,7 @@ void Configure::applySpecSpecifics()
2d2b1a
         dictionary[ "QT_EVDEV" ]            = "no";
2d2b1a
         dictionary[ "QT_MTDEV" ]            = "no";
2d2b1a
         dictionary[ "FONT_CONFIG" ]         = "auto";
2d2b1a
+        dictionary[ "POLL" ]                = "poll";
2d2b1a
         dictionary[ "ANGLE" ]               = "no";
2d2b1a
2d2b1a
         dictionary["DECORATIONS"]           = "default windows styled";
2d2b1a
@@ -1758,6 +1759,7 @@ void Configure::applySpecSpecifics()
2d2b1a
         dictionary[ "QT_XKBCOMMON" ]        = "no";
2d2b1a
         dictionary["ANDROID_STYLE_ASSETS"]  = "yes";
2d2b1a
         dictionary[ "STYLE_ANDROID" ]       = "yes";
2d2b1a
+        dictionary[ "POLL" ]                = "poll";
2d2b1a
     }
2d2b1a
 }
2d2b1a
2d2b1a
@@ -3049,6 +3051,9 @@ void Configure::generateOutputVars()
2d2b1a
     if (dictionary["REDUCE_EXPORTS"] == "yes")
2d2b1a
         qtConfig += "reduce_exports";
2d2b1a
2d2b1a
+    if (!dictionary["POLL"].isEmpty())
2d2b1a
+        qtConfig += "poll_" + dictionary["POLL"];
2d2b1a
+
2d2b1a
     // We currently have no switch for QtConcurrent, so add it unconditionally.
2d2b1a
     qtConfig += "concurrent";
2d2b1a