diff --git a/system/jlib/jsocket.cpp b/system/jlib/jsocket.cpp index 8c41086a3f6..c9e9d36ccbb 100644 --- a/system/jlib/jsocket.cpp +++ b/system/jlib/jsocket.cpp @@ -385,35 +385,38 @@ enum SOCKETMODE { sm_tcp_server, sm_tcp, sm_udp_server, sm_udp, sm_multicast_ser # endif #endif -static CriticalSection queryKACS; +enum UseUDE { UNINIT, INITED }; +static std::atomic expertTCPSettings { UNINIT }; +static CriticalSection queryTCPCS; -enum UseUDE { UNINIT, DISABLED, ENABLED }; -static std::atomic doKeepAlive { UNINIT }; +static bool hasKeepAlive = false; static int keepAliveTime = -1; static int keepAliveInterval = -1; static int keepAliveProbes = -1; +static bool disableDNSTimeout = false; /* - + global: expert: + disableDNSTimeout: false keepalive: time: 200 interval: 75 probes: 9 */ -extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) +static void queryTCPSettings() { - UseUDE state = doKeepAlive.load(); + UseUDE state = expertTCPSettings.load(); if (state == UNINIT) { - CriticalBlock block(queryKACS); - state = doKeepAlive.load(); + CriticalBlock block(queryTCPCS); + state = expertTCPSettings.load(); if (state == UNINIT) { #ifdef _CONTAINERIZED @@ -440,7 +443,6 @@ extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) catch (...) { } - state = DISABLED; if (expert) { IPropertyTree *keepalive = expert->queryPropTree("keepalive"); @@ -449,22 +451,25 @@ extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) keepAliveTime = keepalive->getPropInt("@time", keepAliveTime); keepAliveInterval = keepalive->getPropInt("@interval", keepAliveInterval); keepAliveProbes = keepalive->getPropInt("@probes", keepAliveProbes); - state = ENABLED; + hasKeepAlive = true; } + disableDNSTimeout = expert->getPropBool("@disableDNSTimeout", false); } - doKeepAlive = state; + expertTCPSettings = INITED; } } +} - if (state == ENABLED) +extern jlib_decl bool queryKeepAlive(int &time, int &intvl, int &probes) +{ + queryTCPSettings(); + if (hasKeepAlive) { time = keepAliveTime; intvl = keepAliveInterval; probes = keepAliveProbes; - return true; } - else - return false; + return hasKeepAlive; } static bool getAddressInfo(const char *name, unsigned *netaddr, bool okToLogErr); @@ -476,32 +481,27 @@ static std::list gaPtrList; class GetAddrInfoThread : public Thread { - char name[256]; + StringAttr name; Semaphore semait; - std::atomic started; - std::atomic ended; - unsigned netaddr[4]; - bool result; + std::atomic ended{false}; + unsigned netaddr[4] = { 0, 0, 0, 0 }; + bool result = false; public: - GetAddrInfoThread(const char *_name) : started(false), ended(false), result(false) + GetAddrInfoThread(const char *_name) { - strncpy(name, _name, 255); - name[255] = '\0'; - memset(netaddr, 0, sizeof(netaddr)); + name.set(_name); } bool thrdHasEnded() { - if (started) - return ended; - return false; + return ended; } bool waitms(unsigned timeoutms, unsigned *resAddr) { bool ret = semait.wait(timeoutms); - if (ret && ended) + if (ret) { if (result) memcpy(resAddr, netaddr, sizeof(netaddr)); @@ -518,8 +518,7 @@ class GetAddrInfoThread : public Thread virtual int run() override { - started = true; - result = getAddressInfo(name, netaddr, false); + result = getAddressInfo(name.get(), netaddr, false); ended = true; semait.signal(); return 0; @@ -530,27 +529,33 @@ class GetAddrInfoThread : public Thread class AddrInfoReaperThread : public Thread { public: - std::atomic stopped; + std::atomic stopped{false}; + std::atomic running{false}; Semaphore sem; - AddrInfoReaperThread() : stopped(true) + AddrInfoReaperThread() { } void stop() { - stopped = true; - sem.signal(); - join(); + if (running) { - CriticalBlock block(queryDNSCS); - gaPtrList.clear(); + stopped = true; + sem.signal(); + join(); + running = false; + { + CriticalBlock block(queryDNSCS); + // TODO: wait a short while for running threads to end ... + gaPtrList.clear(); + } } } virtual int run() override { - stopped = false; + running = true; while(!stopped) { { @@ -574,7 +579,7 @@ class AddrInfoReaperThread : public Thread } } } - if (sem.wait(10)) + if (sem.wait(500)) break; } return 0; @@ -582,66 +587,24 @@ class AddrInfoReaperThread : public Thread }; -static std::atomic disableDNSTimeout { UNINIT }; - static Owned addrinforeaperthrd; -static bool queryDNSTimeout() +static bool useDNSTimeout() { - UseUDE state = disableDNSTimeout.load(); - if (state == UNINIT) + queryTCPSettings(); + if (!disableDNSTimeout) { - CriticalBlock block(queryDNSCS); - state = disableDNSTimeout.load(); - if (state == UNINIT) + if (!addrinforeaperthrd) { -#ifdef _CONTAINERIZED - Owned expert; -#else - Owned envtree; - IPropertyTree *expert = nullptr; -#endif - try - { -#ifdef _CONTAINERIZED - expert.setown(getGlobalConfigSP()->getPropTree("expert")); -#else - // MCK - without this many components will not have a global prop - envtree.setown(getHPCCEnvironment()); - if (envtree) - expert = envtree->queryPropTree("Software/Globals"); -#endif - } - catch (IException *e) - { - e->Release(); - } - catch (...) - { - } - state = ENABLED; - if (expert) - { - bool isDisabled = expert->getPropBool("@disableDNSTimeout", false); - if (isDisabled) - state = DISABLED; - } - disableDNSTimeout = state; - - if (state == ENABLED) + CriticalBlock block(queryDNSCS); + if (!addrinforeaperthrd) { - if (!addrinforeaperthrd) - { - addrinforeaperthrd.setown(new AddrInfoReaperThread()); - addrinforeaperthrd->start(false); - } + addrinforeaperthrd.setown(new AddrInfoReaperThread()); + addrinforeaperthrd->start(false); } } - } - - if (state == ENABLED) return true; - + } return false; } @@ -3616,7 +3579,6 @@ bool getAddressInfo(const char *name, unsigned *netaddr, bool okToLogErr) static bool lookupHostAddress(const char *name, unsigned *netaddr, unsigned timeoutms=INFINITE) { // if IP4only or using MS V6 can only resolve IPv4 using - static bool recursioncheck = false; // needed to stop error message recursing int retry=10; #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) @@ -3628,11 +3590,7 @@ static bool lookupHostAddress(const char *name, unsigned *netaddr, unsigned time hostent * entry = gethostbyname(name); while (entry==NULL) { if (retry--==0) { - if (!recursioncheck) { - recursioncheck = true; - LogErr(h_errno,1,"gethostbyname failed",__LINE__,name); - recursioncheck = false; - } + RecursionSafeLogErr(h_errno, 1, "gethostbyname failed", __LINE__, name); return false; } { @@ -3667,7 +3625,7 @@ static bool lookupHostAddress(const char *name, unsigned *netaddr, unsigned time #if defined(__linux__) || defined (__APPLE__) || defined(getaddrinfo) bool ret = false; - if ( (timeoutms != INFINITE) && (queryDNSTimeout()) ) + if ( (timeoutms != INFINITE) && (useDNSTimeout()) ) { // NOTES: // getaddrinfo_a() offers an async getaddrinfo method, but has some limitations and a possible mem leak