Bug 1170646 - Handle short read in (old) Cache code still used by C-C T.B. r=michal
☠☠ backed out by e4e4f6e4f952 ☠ ☠
authorISHIKAWA, Chiaki <ishikawa@yk.rim.or.jp>
Sun, 21 Jun 2015 05:54:00 +0200
changeset 251726 f83eddcbebbc4c2c9554bb2a929f0f25bc6c563d
parent 251725 004e123383ae3ce5c6332b684d7a16ce6b2f5185
child 251727 89ef09135c286244cde0ec474fc971fb4105f70b
push id29007
push userryanvm@gmail.com
push dateTue, 07 Jul 2015 18:38:06 +0000
treeherdermozilla-central@9340658848d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmichal
bugs1170646
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1170646 - Handle short read in (old) Cache code still used by C-C T.B. r=michal
netwerk/cache/nsDiskCacheBlockFile.cpp
--- a/netwerk/cache/nsDiskCacheBlockFile.cpp
+++ b/netwerk/cache/nsDiskCacheBlockFile.cpp
@@ -8,16 +8,43 @@
 #include "nsDiskCache.h"
 #include "nsDiskCacheBlockFile.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include <algorithm>
 
 using namespace mozilla;
 
+/* to cope with short read.
+ * xxx not sure  if we want to repeat PR_Read() if no octet is ever read
+ * and is errno == EINTR
+ */
+static
+ssize_t
+busy_beaver_PR_Read(PRFileDesc *fd, void * start, PRInt32 len)
+{
+    int n;
+    PRInt32 remaining = len;
+
+    while (remaining > 0) {
+        n = PR_Read(fd, start, remaining);
+        if (n < 0) {
+            if( (len - remaining) == 0 ) // no octet is ever read
+                return -1;
+            break;
+        } else {
+            remaining -= n;
+            char *cp = (char *) start;
+            cp += n;
+            start = cp;
+        }
+    }
+    return len - remaining;
+}
+
 /******************************************************************************
  * nsDiskCacheBlockFile - 
  *****************************************************************************/
 
 /******************************************************************************
  *  Open
  *****************************************************************************/
 nsresult
@@ -69,17 +96,17 @@ nsDiskCacheBlockFile::Open(nsIFile * blo
         
     } else if ((uint32_t)mFileSize < bitMapBytes) {
         *corruptInfo = nsDiskCache::kBlockFileSizeLessThanBitMap;
         rv = NS_ERROR_UNEXPECTED;  // XXX NS_ERROR_CACHE_INVALID;
         goto error_exit;
         
     } else {
         // read the bit map
-        const int32_t bytesRead = PR_Read(mFD, mBitMap, bitMapBytes);
+        const int32_t bytesRead = busy_beaver_PR_Read(mFD, mBitMap, bitMapBytes);
         if ((bytesRead < 0) || ((uint32_t)bytesRead < bitMapBytes)) {
             *corruptInfo = nsDiskCache::kBlockFileBitMapReadError;
             rv = NS_ERROR_UNEXPECTED;
             goto error_exit;
         }
 #if defined(IS_LITTLE_ENDIAN)
         // Swap from network format
         for (unsigned int i = 0; i < mBitMapWords; ++i)
@@ -248,21 +275,25 @@ nsDiskCacheBlockFile::ReadBlocks( void *
     int32_t filePos = PR_Seek(mFD, blockPos, PR_SEEK_SET);
     if (filePos != blockPos)  return NS_ERROR_UNEXPECTED;
 
     // read the blocks
     int32_t bytesToRead = *bytesRead;
     if ((bytesToRead <= 0) || ((uint32_t)bytesToRead > mBlockSize * numBlocks)) {
         bytesToRead = mBlockSize * numBlocks;
     }
-    *bytesRead = PR_Read(mFD, buffer, bytesToRead);
-    
+    /* This has to tolerate short read, i.e., we need to repeat! */
+    *bytesRead = busy_beaver_PR_Read(mFD, buffer, bytesToRead);
+
     CACHE_LOG_DEBUG(("CACHE: nsDiskCacheBlockFile::Read [this=%p] "
                      "returned %d / %d bytes", this, *bytesRead, bytesToRead));
 
+    if(*bytesRead == -1)
+        return NS_ERROR_UNEXPECTED;
+
     return NS_OK;
 }
 
 
 /******************************************************************************
  *  FlushBitMap
  *****************************************************************************/
 nsresult