bug 887753 - server not found after reconnecting to etherpad r=sworkman
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 19 Jul 2013 18:40:00 -0400
changeset 139596 540de81dc1769323a9991306947d57c4b0dfc0bd
parent 139595 8c2e8714201fc9083b909fe34d6431115afce2d2
child 139597 955975fb2ca768f7d966fd6bfd5766e556aeae10
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewerssworkman
bugs887753
milestone25.0a1
bug 887753 - server not found after reconnecting to etherpad r=sworkman
netwerk/dns/nsHostResolver.cpp
netwerk/dns/nsHostResolver.h
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -126,30 +126,51 @@ public:
 private:
     PRIntervalTime mLastReset;
 };
 
 #endif // RES_RETRY_ON_FAILURE
 
 //----------------------------------------------------------------------------
 
+static inline bool
+IsHighPriority(uint16_t flags)
+{
+    return !(flags & (nsHostResolver::RES_PRIORITY_LOW | nsHostResolver::RES_PRIORITY_MEDIUM));
+}
+
+static inline bool
+IsMediumPriority(uint16_t flags)
+{
+    return flags & nsHostResolver::RES_PRIORITY_MEDIUM;
+}
+
+static inline bool
+IsLowPriority(uint16_t flags)
+{
+    return flags & nsHostResolver::RES_PRIORITY_LOW;
+}
+
+//----------------------------------------------------------------------------
+
 // this macro filters out any flags that are not used when constructing the
 // host key.  the significant flags are those that would affect the resulting
 // host record (i.e., the flags that are passed down to PR_GetAddrInfoByName).
 #define RES_KEY_FLAGS(_f) ((_f) & nsHostResolver::RES_CANON_NAME)
 
 nsHostRecord::nsHostRecord(const nsHostKey *key)
     : addr_info_lock("nsHostRecord.addr_info_lock")
     , addr_info_gencnt(0)
     , addr_info(nullptr)
     , addr(nullptr)
     , negative(false)
     , resolving(false)
     , onQueue(false)
     , usingAnyThread(false)
+    , mDoomed(false)
 {
     host = ((char *) this) + sizeof(nsHostRecord);
     memcpy((char *) host, key->host, strlen(key->host) + 1);
     flags = key->flags;
     af = key->af;
 
     expiration = TimeStamp::NowLoRes();
 
@@ -208,31 +229,47 @@ nsHostRecord::Blacklisted(NetAddr *aQuer
 }
 
 void
 nsHostRecord::ReportUnusable(NetAddr *aAddress)
 {
     // must call locked
     LOG(("Adding address to blacklist for host [%s], host record [%p].\n", host, this));
 
+    if (negative)
+        mDoomed = true;
+
     char buf[kIPv6CStrBufSize];
     if (NetAddrToString(aAddress, buf, sizeof(buf))) {
         LOG(("Successfully adding address [%s] to blacklist for host [%s].\n", buf, host));
         mBlacklistedItems.AppendElement(nsCString(buf));
     }
 }
 
 void
 nsHostRecord::ResetBlacklist()
 {
     // must call locked
     LOG(("Resetting blacklist for host [%s], host record [%p].\n", host, this));
     mBlacklistedItems.Clear();
 }
 
+bool
+nsHostRecord::HasUsableResult(uint16_t queryFlags) const
+{
+    if (mDoomed)
+        return false;
+
+    // don't use cached negative results for high priority queries.
+    if (negative && IsHighPriority(queryFlags))
+        return false;
+
+    return addr_info || addr || negative;
+}
+
 //----------------------------------------------------------------------------
 
 struct nsHostDBEnt : PLDHashEntryHdr
 {
     nsHostRecord *rec;
 };
 
 static PLDHashNumber
@@ -458,34 +495,16 @@ nsHostResolver::Shutdown()
 
     PRIntervalTime delay = PR_MillisecondsToInterval(25);
     PRIntervalTime stopTime = PR_IntervalNow() + PR_SecondsToInterval(20);
     while (mThreadCount && PR_IntervalNow() < stopTime)
         PR_Sleep(delay);
 #endif
 }
 
-static inline bool
-IsHighPriority(uint16_t flags)
-{
-    return !(flags & (nsHostResolver::RES_PRIORITY_LOW | nsHostResolver::RES_PRIORITY_MEDIUM));
-}
-
-static inline bool
-IsMediumPriority(uint16_t flags)
-{
-    return flags & nsHostResolver::RES_PRIORITY_MEDIUM;
-}
-
-static inline bool
-IsLowPriority(uint16_t flags)
-{
-    return flags & nsHostResolver::RES_PRIORITY_LOW;
-}
-
 void 
 nsHostResolver::MoveQueue(nsHostRecord *aRec, PRCList &aDestQ)
 {
     NS_ASSERTION(aRec->onQueue, "Moving Host Record Not Currently Queued");
     
     PR_REMOVE_LINK(aRec);
     PR_APPEND_LINK(aRec, &aDestQ);
 }
@@ -532,17 +551,17 @@ nsHostResolver::ResolveHost(const char  
             nsHostDBEnt *he = static_cast<nsHostDBEnt *>
                                          (PL_DHashTableOperate(&mDB, &key, PL_DHASH_ADD));
 
             // if the record is null, then HostDB_InitEntry failed.
             if (!he || !he->rec)
                 rv = NS_ERROR_OUT_OF_MEMORY;
             // do we have a cached result that we can reuse?
             else if (!(flags & RES_BYPASS_CACHE) &&
-                     he->rec->HasResult() &&
+                     he->rec->HasUsableResult(flags) &&
                      TimeStamp::NowLoRes() <= (he->rec->expiration + TimeDuration::FromSeconds(mGracePeriod * 60))) {
                 LOG(("Using cached record for host [%s].\n", host));
                 // put reference to host record on stack...
                 result = he->rec;
                 Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_HIT);
 
                 // For entries that are in the grace period with a failed connect,
                 // or all cached negative entries, use the cache but start a new lookup in
--- a/netwerk/dns/nsHostResolver.h
+++ b/netwerk/dns/nsHostResolver.h
@@ -75,17 +75,17 @@ public:
     mozilla::net::NetAddr  *addr;
     bool         negative;   /* True if this record is a cache of a failed lookup.
                                 Negative cache entries are valid just like any other
                                 (though never for more than 60 seconds), but a use
                                 of that negative entry forces an asynchronous refresh. */
 
     mozilla::TimeStamp expiration;
 
-    bool HasResult() const { return addr_info || addr || negative; }
+    bool HasUsableResult(uint16_t queryFlags) const;
 
     // hold addr_info_lock when calling the blacklist functions
     bool   Blacklisted(mozilla::net::NetAddr *query);
     void   ResetBlacklist();
     void   ReportUnusable(mozilla::net::NetAddr *addr);
 
 private:
     friend class nsHostResolver;
@@ -93,16 +93,17 @@ private:
     PRCList callbacks; /* list of callbacks */
 
     bool    resolving; /* true if this record is being resolved, which means
                         * that it is either on the pending queue or owned by
                         * one of the worker threads. */ 
     
     bool    onQueue;  /* true if pending and on the queue (not yet given to getaddrinfo())*/
     bool    usingAnyThread; /* true if off queue and contributing to mActiveAnyThreadCount */
+    bool    mDoomed; /* explicitly expired */
 
     // a list of addresses associated with this record that have been reported
     // as unusable. the list is kept as a set of strings to make it independent
     // of gencnt.
     nsTArray<nsCString> mBlacklistedItems;
 
     nsHostRecord(const nsHostKey *key);           /* use Create() instead */
    ~nsHostRecord();