summaryrefslogtreecommitdiffstats
path: root/src/network/kernel/qhostinfo_unix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/kernel/qhostinfo_unix.cpp')
-rw-r--r--src/network/kernel/qhostinfo_unix.cpp74
1 files changed, 56 insertions, 18 deletions
diff --git a/src/network/kernel/qhostinfo_unix.cpp b/src/network/kernel/qhostinfo_unix.cpp
index 8d2cffc304..d22608e22f 100644
--- a/src/network/kernel/qhostinfo_unix.cpp
+++ b/src/network/kernel/qhostinfo_unix.cpp
@@ -79,6 +79,11 @@ QT_BEGIN_NAMESPACE
# define Q_ADDRCONFIG AI_ADDRCONFIG
#endif
+enum LibResolvFeature {
+ NeedResInit,
+ NeedResNInit
+};
+
typedef struct __res_state *res_state_ptr;
typedef int (*res_init_proto)(void);
@@ -89,9 +94,29 @@ typedef void (*res_nclose_proto)(res_state_ptr);
static res_nclose_proto local_res_nclose = 0;
static res_state_ptr local_res = 0;
-static bool resolveLibraryInternal()
-{
#if QT_CONFIG(library) && !defined(Q_OS_QNX)
+namespace {
+struct LibResolv
+{
+ enum {
+#ifdef RES_NORELOAD
+ // If RES_NORELOAD is defined, then the libc is capable of watching
+ // /etc/resolv.conf for changes and reloading as necessary. So accept
+ // whatever is configured.
+ ReinitNecessary = false
+#else
+ ReinitNecessary = true
+#endif
+ };
+
+ QLibrary lib;
+ LibResolv();
+ ~LibResolv() { lib.unload(); }
+};
+}
+
+LibResolv::LibResolv()
+{
QLibrary lib;
#ifdef LIBRESOLV_SO
lib.setFileName(QStringLiteral(LIBRESOLV_SO));
@@ -100,32 +125,45 @@ static bool resolveLibraryInternal()
{
lib.setFileName(QLatin1String("resolv"));
if (!lib.load())
- return false;
+ return;
}
- local_res_init = res_init_proto(lib.resolve("__res_init"));
- if (!local_res_init)
- local_res_init = res_init_proto(lib.resolve("res_init"));
-
+ // res_ninit is required for localDomainName()
local_res_ninit = res_ninit_proto(lib.resolve("__res_ninit"));
if (!local_res_ninit)
local_res_ninit = res_ninit_proto(lib.resolve("res_ninit"));
-
- if (!local_res_ninit) {
- // if we can't get a thread-safe context, we have to use the global _res state
- local_res = res_state_ptr(lib.resolve("_res"));
- } else {
+ if (local_res_ninit) {
+ // we must now find res_nclose
local_res_nclose = res_nclose_proto(lib.resolve("res_nclose"));
if (!local_res_nclose)
local_res_nclose = res_nclose_proto(lib.resolve("__res_nclose"));
if (!local_res_nclose)
- local_res_ninit = 0;
+ local_res_ninit = nullptr;
}
-#endif
- return true;
+ if (ReinitNecessary || !local_res_ninit) {
+ local_res_init = res_init_proto(lib.resolve("__res_init"));
+ if (!local_res_init)
+ local_res_init = res_init_proto(lib.resolve("res_init"));
+
+ if (local_res_init && !local_res_ninit) {
+ // if we can't get a thread-safe context, we have to use the global _res state
+ local_res = res_state_ptr(lib.resolve("_res"));
+ }
+ }
+}
+Q_GLOBAL_STATIC(LibResolv, libResolv)
+
+static void resolveLibrary(LibResolvFeature f)
+{
+ if (LibResolv::ReinitNecessary || f == NeedResNInit)
+ libResolv();
+}
+#else // QT_CONFIG(library) || Q_OS_QNX
+static void resolveLibrary(LibResolvFeature)
+{
}
-Q_GLOBAL_STATIC_WITH_ARGS(bool, resolveLibrary, (resolveLibraryInternal()))
+#endif // QT_CONFIG(library) || Q_OS_QNX
QHostInfo QHostInfoAgent::fromName(const QString &hostName)
{
@@ -137,7 +175,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
#endif
// Load res_init on demand.
- resolveLibrary();
+ resolveLibrary(NeedResInit);
// If res_init is available, poll it.
if (local_res_init)
@@ -275,7 +313,7 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName)
QString QHostInfo::localDomainName()
{
#if !defined(Q_OS_VXWORKS) && !defined(Q_OS_ANDROID)
- resolveLibrary();
+ resolveLibrary(NeedResNInit);
if (local_res_ninit) {
// using thread-safe version
res_state_ptr state = res_state_ptr(malloc(sizeof(*state)));