|
|
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 |
|