diff options
author | Liang Qi <liang.qi@qt.io> | 2017-08-31 13:10:18 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-08-31 14:31:31 +0200 |
commit | 112a4af10741409b3d8503cb77852a777b607ce0 (patch) | |
tree | fa99f0f37fc1505522fe9368e95484c7732ccda8 /src/network/kernel | |
parent | 29ef0d2bccd1874e20de94485ee05777c3a95c5d (diff) | |
parent | e938150412d22e61926fe16791158805b71268bb (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts:
examples/examples.pro
qmake/library/qmakebuiltins.cpp
src/corelib/global/qglobal.cpp
Re-apply b525ec2 to qrandom.cpp(code movement in 030782e)
src/corelib/global/qnamespace.qdoc
src/corelib/global/qrandom.cpp
src/gui/kernel/qwindow.cpp
Re-apply a3d59c7 to QWindowPrivate::setVisible() (code movement in d7a9e08)
src/network/ssl/qsslkey_openssl.cpp
src/plugins/platforms/android/androidjniinput.cpp
src/plugins/platforms/xcb/qxcbconnection.cpp
src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
src/widgets/widgets/qmenu.cpp
tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
Change-Id: If7ab427804408877a93cbe02079fca58e568bfd3
Diffstat (limited to 'src/network/kernel')
-rw-r--r-- | src/network/kernel/kernel.pri | 2 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo_unix.cpp | 3 | ||||
-rw-r--r-- | src/network/kernel/qnetworkinterface_unix.cpp | 5 | ||||
-rw-r--r-- | src/network/kernel/qnetworkproxy_libproxy.cpp | 143 |
4 files changed, 121 insertions, 32 deletions
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index c3fcf25233..ac6bebbfae 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -63,6 +63,6 @@ osx:SOURCES += kernel/qnetworkproxy_mac.cpp else:win32:!winrt: SOURCES += kernel/qnetworkproxy_win.cpp else: qtConfig(libproxy) { SOURCES += kernel/qnetworkproxy_libproxy.cpp - QMAKE_USE_PRIVATE += libproxy + QMAKE_USE_PRIVATE += libproxy libdl } else:SOURCES += kernel/qnetworkproxy_generic.cpp diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp index cf08a15f96..9a24938284 100644 --- a/src/network/kernel/qhostinfo_unix.cpp +++ b/src/network/kernel/qhostinfo_unix.cpp @@ -150,8 +150,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) QHostAddress address; if (address.setAddress(hostName)) { // Reverse lookup -// Reverse lookups using getnameinfo are broken on darwin, use gethostbyaddr instead. -#if !defined (QT_NO_GETADDRINFO) && !defined (Q_OS_DARWIN) +#if !defined (QT_NO_GETADDRINFO) sockaddr_in sa4; sockaddr_in6 sa6; sockaddr *sa = 0; diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 4f4615d4d0..afa6b4296e 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -60,11 +60,6 @@ # define QT_NO_GETIFADDRS #endif -#ifdef Q_OS_ANDROID -// android lacks if_nameindex -# define QT_NO_IPV6IFNAME -#endif - #ifdef Q_OS_HAIKU # include <sys/sockio.h> # define IFF_RUNNING 0x0001 diff --git a/src/network/kernel/qnetworkproxy_libproxy.cpp b/src/network/kernel/qnetworkproxy_libproxy.cpp index 184dc6469d..29d2a0bd3b 100644 --- a/src/network/kernel/qnetworkproxy_libproxy.cpp +++ b/src/network/kernel/qnetworkproxy_libproxy.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -42,57 +43,149 @@ #ifndef QT_NO_NETWORKPROXY #include <QtCore/QByteArray> +#include <QtCore/QMutex> +#include <QtCore/QSemaphore> #include <QtCore/QUrl> +#include <QtCore/private/qeventdispatcher_unix_p.h> +#include <QtCore/private/qthread_p.h> #include <proxy.h> +#include <dlfcn.h> QT_BEGIN_NAMESPACE -class QLibProxyWrapper +static bool isThreadingNeeded() { -public: - QLibProxyWrapper() - : factory(px_proxy_factory_new()) - { - if (!factory) - qWarning("libproxy initialization failed."); - } + // Try to guess if the libproxy we linked to is from the libproxy project + // or if it is from pacrunner. Neither library is thread-safe, but the one + // from libproxy is worse, since it may launch JS engines that don't take + // kindly to being executed from multiple threads (even if at different + // times). The pacrunner implementation doesn't suffer from this because + // the JS execution is out of process, in the pacrunner daemon. - ~QLibProxyWrapper() - { - px_proxy_factory_free(factory); - } + void *sym; + +#ifdef Q_CC_GNU + // Search for the mangled name of the virtual table of the pacrunner + // extension. Even if libproxy begins using -fvisibility=hidden, this + // symbol can't be hidden. + sym = dlsym(RTLD_DEFAULT, "_ZTVN8libproxy19pacrunner_extensionE"); +#else + // The default libproxy one uses libmodman for its module management and + // leaks symbols because it doesn't use -fvisibility=hidden (as of + // v0.4.15). + sym = dlsym(RTLD_DEFAULT, "mm_info_ignore_hostname"); +#endif + + return sym != nullptr; +} + +class QLibProxyWrapper : public QDaemonThread +{ + Q_OBJECT +public: + QLibProxyWrapper(); + ~QLibProxyWrapper(); QList<QUrl> getProxies(const QUrl &url); private: - pxProxyFactory *factory; + struct Data { + // we leave the conversion to/from QUrl to the calling thread + const char *url; + char **proxies; + QSemaphore replyReady; + }; + + void run() override; + + pxProxyFactory *factory; // not subject to the mutex + + QMutex mutex; + QSemaphore requestReady; + Data *request; }; Q_GLOBAL_STATIC(QLibProxyWrapper, libProxyWrapper); +QLibProxyWrapper::QLibProxyWrapper() +{ + if (isThreadingNeeded()) { + setEventDispatcher(new QEventDispatcherUNIX); // don't allow the Glib one + start(); + } else { + factory = px_proxy_factory_new(); + Q_CHECK_PTR(factory); + } +} + +QLibProxyWrapper::~QLibProxyWrapper() +{ + if (isRunning()) { + requestInterruption(); + requestReady.release(); + wait(); + } else { + px_proxy_factory_free(factory); + } +} + /* - Gets the list of proxies from libproxy, converted to QUrl list. - Thread safe, according to libproxy documentation. + Gets the list of proxies from libproxy, converted to QUrl list. Apply + thread-safety, though its documentation says otherwise, libproxy isn't + thread-safe. */ QList<QUrl> QLibProxyWrapper::getProxies(const QUrl &url) { - QList<QUrl> ret; + QByteArray encodedUrl = url.toEncoded(); + Data data; + data.url = encodedUrl.constData(); + + { + QMutexLocker locker(&mutex); + if (isRunning()) { + // threaded mode + // it's safe to write to request because we hold the mutex: + // our aux thread is blocked waiting for work and no other thread + // could have got here + request = &data; + requestReady.release(); - if (factory) { - char **proxies = px_proxy_factory_get_proxies(factory, url.toEncoded()); - if (proxies) { - for (int i = 0; proxies[i]; i++) { - ret.append(QUrl::fromEncoded(proxies[i])); - free(proxies[i]); - } - free(proxies); + // wait for the reply + data.replyReady.acquire(); + } else { + // non-threaded mode + data.proxies = px_proxy_factory_get_proxies(factory, data.url); } } + QList<QUrl> ret; + if (data.proxies) { + for (int i = 0; data.proxies[i]; i++) { + ret.append(QUrl::fromEncoded(data.proxies[i])); + free(data.proxies[i]); + } + free(data.proxies); + } return ret; } +void QLibProxyWrapper::run() +{ + factory = px_proxy_factory_new(); + Q_CHECK_PTR(factory); + + forever { + requestReady.acquire(); + if (isInterruptionRequested()) + break; + request->proxies = px_proxy_factory_get_proxies(factory, request->url); + request->replyReady.release(); + } + + px_proxy_factory_free(factory); +} + QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) { QList<QNetworkProxy> proxyList; @@ -161,4 +254,6 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro QT_END_NAMESPACE +#include "qnetworkproxy_libproxy.moc" + #endif |