bug 1242030: DONT-USE-REUSABLE new part-4 new splitting of (consolidation of 1122698, 1134527, 1134529, 1174500) draft
authorISHIKAWA, Chiaki <ishikawa@yk.rim.or.jp>
Sat, 09 Nov 2019 11:11:57 +0900
changeset 81101 380ec5a67f05dbc96d31b262be2dbf01737f3df4
parent 81100 4d3a3af883688418c0676b06f7bcc4542bf565ea
child 81102 a1fa995a885e034c98b434ec943077d204ce27d6
push id9745
push userishikawa@yk.rim.or.jp
push dateSat, 09 Nov 2019 02:12:14 +0000
treeherdertry-comm-central@f62e5475decc [default view] [failures only]
bugs1242030, 1122698, 1134527, 1134529, 1174500
bug 1242030: DONT-USE-REUSABLE new part-4 new splitting of (consolidation of 1122698, 1134527, 1134529, 1174500)
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsMailboxProtocol.cpp
mailnews/local/src/nsMovemailService.cpp
mailnews/local/src/nsMsgBrkMBoxStore.cpp
mailnews/local/src/nsMsgLocalStoreUtils.cpp
mailnews/local/src/nsMsgMaildirStore.cpp
mailnews/local/src/nsParseMailbox.cpp
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -54,16 +54,20 @@
 #include "nsNetUtil.h"
 #include "nsIMsgFolderNotificationService.h"
 #include "nsReadLine.h"
 #include "nsArrayUtils.h"
 #include "nsIStringEnumerator.h"
 #include "mozilla/Services.h"
 #include "nsIURIMutator.h"
 
+/* for logging to Error Console */
+#include "nsIScriptError.h"
+#include "nsIConsoleService.h"
+
 //////////////////////////////////////////////////////////////////////////////
 // nsLocal
 /////////////////////////////////////////////////////////////////////////////
 
 nsLocalMailCopyState::nsLocalMailCopyState()
     : m_flags(0),
       m_lastProgressTime(PR_IntervalToMilliseconds(PR_IntervalNow())),
       m_curDstKey(nsMsgKey_None),
@@ -73,18 +77,24 @@ nsLocalMailCopyState::nsLocalMailCopySta
       m_leftOver(0),
       m_isMove(false),
       m_dummyEnvelopeNeeded(false),
       m_fromLineSeen(false),
       m_writeFailed(false),
       m_notifyFolderLoaded(false) {}
 
 nsLocalMailCopyState::~nsLocalMailCopyState() {
+  nsresult rv;
   PR_Free(m_dataBuffer);
-  if (m_fileStream) m_fileStream->Close();
+  if (m_fileStream) {
+    rv = m_fileStream->Close();
+    // NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "close failed: m_fileStream->Close.");
+    if (NS_FAILED(rv)) NS_WARNING("close failed: m_fileStream->Close.");
+    m_fileStream = nullptr;  // code uniformity
+  }
   if (m_messageService) {
     nsCOMPtr<nsIMsgFolder> srcFolder = do_QueryInterface(m_srcSupport);
     if (srcFolder && m_message) {
       nsCString uri;
       srcFolder->GetUriForMsg(m_message, uri);
     }
   }
 }
@@ -306,18 +316,21 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetD
           mDatabase->ForceClosed();
 
         mDatabase = nullptr;
       }
       nsCOMPtr<nsIFile> summaryFile;
       rv = GetSummaryFileLocation(pathFile, getter_AddRefs(summaryFile));
       NS_ENSURE_SUCCESS(rv, rv);
       // Remove summary file.
-      summaryFile->Remove(false);
-
+      rv = summaryFile->Remove(false);
+      // Not sure if need to check this error, but be conservative.
+      if (NS_FAILED(rv)) {
+        NS_WARNING("Could not delete msg summary file");
+      }
       // if it's out of date then reopen with upgrade.
       rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (transferInfo && mDatabase) {
         SetDBTransferInfo(transferInfo);
         mDatabase->SetSummaryValid(false);
       }
@@ -451,16 +464,26 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Crea
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::CreateSubfolder(const nsAString &folderName,
                                       nsIMsgWindow *msgWindow) {
   nsCOMPtr<nsIMsgFolder> newFolder;
   nsresult rv =
       CreateSubfolderInternal(folderName, msgWindow, getter_AddRefs(newFolder));
+#ifdef DEBUG
+  if (NS_FAILED(rv)) {
+    fprintf(stderr,
+            "(debug) nsMsgLocalMailFolder::CreateSubfolder: "
+            "CreateSubfolder(folderName, ...) failed. rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+    fprintf(stderr, "(debug) folderName = <<%s>>\n",
+            NS_ConvertUTF16toUTF8(folderName).get());
+  }
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgFolderNotificationService> notifier(
       do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
   if (notifier) notifier->NotifyFolderAdded(newFolder);
 
   return NS_OK;
 }
@@ -873,19 +896,20 @@ nsresult nsMsgLocalMailFolder::OpenDatab
     if (parent) {
       // This little dance creates an empty .msf file and then checks
       // if the db is valid - this works if the folder is empty, which
       // we don't have a direct way of checking.
       nsCOMPtr<nsIMsgDatabase> db;
       rv = msgDBService->CreateNewDB(this, getter_AddRefs(db));
       if (db) {
         UpdateSummaryTotals(true);
-        db->Close(true);
+        rv = db->Close(true);
+        if (NS_FAILED(rv)) NS_WARNING("db->Close(true) failed.");
+        db = nullptr;
         mDatabase = nullptr;
-        db = nullptr;
         rv = msgDBService->OpenFolderDB(this, false, getter_AddRefs(mDatabase));
         if (NS_FAILED(rv)) mDatabase = nullptr;
       }
     }
   } else if (NS_FAILED(rv))
     mDatabase = nullptr;
 
   return rv;
@@ -1470,25 +1494,45 @@ nsMsgLocalMailFolder::CopyMessages(nsIMs
   if (numMsgs > 1 &&
       ((MsgLowerCaseEqualsLiteral(protocolType, "imap") && !WeAreOffline()) ||
        MsgLowerCaseEqualsLiteral(protocolType, "mailbox"))) {
     mCopyState->m_copyingMultipleMessages = true;
     rv = CopyMessagesTo(mCopyState->m_messages, keyArray, msgWindow, this,
                         isMove);
     if (NS_FAILED(rv)) {
       NS_ERROR("copy message failed");
+#ifdef DEBUG
+      // NS_ERROR("copy message failed"); We hit this error during Windows
+      // xpcshell-test when the patch to enable buffering was tested, so we dump
+      // context infomration.
+      fprintf(stderr,
+              "(debug) Copy message failed.\n"
+              "rv = CopyMessagesTo(mCopyState->m_messages, keyArray, "
+              "msgWindow, this, isMove);\n"
+              "rv =0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv));
+#endif
       (void)OnCopyCompleted(srcSupport, false);
     }
   } else {
     nsCOMPtr<nsISupports> msgSupport =
         do_QueryElementAt(mCopyState->m_messages, 0);
     if (msgSupport) {
       rv = CopyMessageTo(msgSupport, this, msgWindow, isMove);
       if (NS_FAILED(rv)) {
-        NS_ASSERTION(false, "copy message failed");
+#ifdef DEBUG
+        // NS_ERROR("copy message failed"); We hit this error during Windows
+        // xpcshell-test when the patch to enable buffering was tested, so we
+        // dump context infomration.
+        fprintf(stderr,
+                "(debug) Copy message failed.\n"
+                "rv = CopyMessageTo(msgSupport, this, msgWindow, isMove);\n"
+                "rv =0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv));
+#endif
         (void)OnCopyCompleted(srcSupport, false);
       }
     }
   }
   // if this failed immediately, need to turn back on notifications and inform
   // FE.
   if (NS_FAILED(rv)) {
     if (isMove) srcFolder->NotifyFolderEvent(kDeleteOrMoveMsgFailed);
@@ -1659,16 +1703,20 @@ nsMsgLocalMailFolder::CopyFolderLocal(ns
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return msgStore->CopyFolder(srcFolder, this, isMoveFolder, msgWindow,
                               aListener, newFolderName);
 }
 
+// XXX TODO Better construct for error handling.
+// We can use goto to clean this routine up!
+// With the current code, it is not clear how to add error recover, etc. for
+// Seek error, for example.
 NS_IMETHODIMP
 nsMsgLocalMailFolder::CopyFileMessage(nsIFile *aFile, nsIMsgDBHdr *msgToReplace,
                                       bool isDraftOrTemplate,
                                       uint32_t newMsgFlags,
                                       const nsACString &aNewMsgKeywords,
                                       nsIMsgWindow *msgWindow,
                                       nsIMsgCopyServiceListener *listener) {
   NS_ENSURE_ARG_POINTER(aFile);
@@ -1728,17 +1776,21 @@ nsMsgLocalMailFolder::CopyFileMessage(ns
 
     // mDatabase should have been initialized above - if we got msgDb
     // If we were going to delete, here is where we would do it. But because
     // existing code already supports doing those deletes, we are just going
     // to end the copy.
     if (NS_SUCCEEDED(rv) && msgToReplace && mDatabase)
       rv = OnCopyCompleted(fileSupport, true);
 
-    if (inputStream) inputStream->Close();
+    if (inputStream) {
+      nsresult rv3 = inputStream->Close();
+      if (NS_FAILED(rv3)) NS_WARNING("inputStream->Close failed");
+      inputStream = nullptr;  // code uniformity
+    }
   }
 
   if (NS_FAILED(rv)) (void)OnCopyCompleted(fileSupport, false);
 
   return rv;
 }
 
 nsresult nsMsgLocalMailFolder::DeleteMessage(nsISupports *message,
@@ -1794,16 +1846,33 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetN
                ? localMailServer->GetNewMail(aWindow, aListener, inbox, nullptr)
                : localInbox->SetCheckForNewMessagesAfterParsing(true);
     }
   }
   return rv;
 }
 
 nsresult nsMsgLocalMailFolder::WriteStartOfNewMessage() {
+  //
+  // Flushing so that we can catch the error from Flush explicitly when
+  // buffering is enabled.
+  //
+
+  nsresult rv1 = mCopyState->m_fileStream->Flush();
+  if (NS_FAILED(rv1)) {
+#ifdef DEBUG
+    fflush(stdout);
+    fprintf(stderr,
+            "(debug) Extra %d: mCopyState->m_fileStream->Flush() returned "
+            "0x%" PRIx32 " in WriteStartOfNewMEssage \n",
+            __LINE__, static_cast<uint32_t>(rv1));
+#endif
+    NS_WARNING("mCopyState->m_fileStream->Flush() failed;");
+  }
+
   nsCOMPtr<nsISeekableStream> seekableStream =
       do_QueryInterface(mCopyState->m_fileStream);
   int64_t filePos;
   seekableStream->Tell(&filePos);
 
   // CopyFileMessage() and CopyMessages() from servers other than pop3
   if (mCopyState->m_parseMsgState) {
     if (mCopyState->m_parseMsgState->m_newMsgHdr)
@@ -1837,52 +1906,84 @@ nsresult nsMsgLocalMailFolder::WriteStar
           statusStrBuf, sizeof(statusStrBuf),
           X_MOZILLA_STATUS_FORMAT MSG_LINEBREAK,
           dbFlags &
               ~(nsMsgMessageFlags::RuntimeOnly | nsMsgMessageFlags::Offline) &
               0x0000FFFF);
     } else
       strcpy(statusStrBuf, "X-Mozilla-Status: 0001" MSG_LINEBREAK);
     uint32_t bytesWritten;
-    mCopyState->m_fileStream->Write(result.get(), result.Length(),
-                                    &bytesWritten);
+    nsresult rv4 = mCopyState->m_fileStream->Write(
+        result.get(), result.Length(), &bytesWritten);
+
+    if (NS_FAILED(rv4) || result.Length() != bytesWritten) {
+      MOZ_ASSERT(NS_SUCCEEDED(rv4) && result.Length() == bytesWritten,
+                 "mCopyState->m_fileStream->Write(result.get(), "
+                 "result.Length(), &bytesWritten) failed.");
+      // XXX TODO better error processing.
+    }
+
     if (mCopyState->m_parseMsgState)
       mCopyState->m_parseMsgState->ParseAFolderLine(result.get(),
                                                     result.Length());
-    mCopyState->m_fileStream->Write(statusStrBuf, strlen(statusStrBuf),
-                                    &bytesWritten);
+    rv4 = mCopyState->m_fileStream->Write(statusStrBuf, strlen(statusStrBuf),
+                                          &bytesWritten);
+
+    if (NS_FAILED(rv4) || strlen(statusStrBuf) != bytesWritten) {
+      MOZ_ASSERT(NS_SUCCEEDED(rv4) && strlen(statusStrBuf) == bytesWritten,
+                 "mCopyState->m_fileStream->Write(statusStrBuf, "
+                 "strlen(statusStrBuf), &bytesWritten) failed.");
+      // XXX TODO better error processing.
+    }
+
     if (mCopyState->m_parseMsgState)
       mCopyState->m_parseMsgState->ParseAFolderLine(statusStrBuf,
                                                     strlen(statusStrBuf));
     result = "X-Mozilla-Status2: 00000000" MSG_LINEBREAK;
-    mCopyState->m_fileStream->Write(result.get(), result.Length(),
-                                    &bytesWritten);
+
+    rv4 = mCopyState->m_fileStream->Write(result.get(), result.Length(),
+                                          &bytesWritten);
+
+    if (NS_FAILED(rv4) || result.Length() != bytesWritten) {
+      MOZ_ASSERT(NS_SUCCEEDED(rv4) && result.Length() == bytesWritten,
+                 "mCopyState->m_fileStream->Write(result.get(), "
+                 "result.Length(), &bytesWritten) failed.");
+      // XXX TODO better error processing.
+    }
+
     if (mCopyState->m_parseMsgState)
       mCopyState->m_parseMsgState->ParseAFolderLine(result.get(),
                                                     result.Length());
     result = X_MOZILLA_KEYWORDS;
-    mCopyState->m_fileStream->Write(result.get(), result.Length(),
-                                    &bytesWritten);
+
+    rv4 = mCopyState->m_fileStream->Write(result.get(), result.Length(),
+                                          &bytesWritten);
+    if (NS_FAILED(rv4) || result.Length() != bytesWritten) {
+      MOZ_ASSERT(NS_SUCCEEDED(rv4) && result.Length() == bytesWritten,
+                 "mCopyState->m_fileStream->Write(result.get(), "
+                 "result.Length(), &bytesWritten) failed.");
+      // XXX TODO better error processing.
+    }
+
     if (mCopyState->m_parseMsgState)
       mCopyState->m_parseMsgState->ParseAFolderLine(result.get(),
                                                     result.Length());
     mCopyState->m_fromLineSeen = true;
   } else
     mCopyState->m_fromLineSeen = false;
 
   mCopyState->m_curCopyIndex++;
   return NS_OK;
 }
 
 nsresult nsMsgLocalMailFolder::InitCopyMsgHdrAndFileStream() {
   nsresult rv = GetMsgStore(getter_AddRefs(mCopyState->m_msgStore));
   NS_ENSURE_SUCCESS(rv, rv);
-  bool reusable;
   rv = mCopyState->m_msgStore->GetNewMsgOutputStream(
-      this, getter_AddRefs(mCopyState->m_newHdr), &reusable,
+      this, getter_AddRefs(mCopyState->m_newHdr),
       getter_AddRefs(mCopyState->m_fileStream));
   NS_ENSURE_SUCCESS(rv, rv);
   if (mCopyState->m_parseMsgState)
     mCopyState->m_parseMsgState->SetNewMsgHdr(mCopyState->m_newHdr);
   return rv;
 }
 
 // nsICopyMessageListener
@@ -1952,16 +2053,19 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Copy
     mCopyState->m_dataBufferSize = aLength + mCopyState->m_leftOver + 3;
   }
 
   nsCOMPtr<nsISeekableStream> seekableStream =
       do_QueryInterface(mCopyState->m_fileStream, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
 
+  // BTW, under Linux, and for POP3 case, Read is handled by recvfrom in
+  // lower-level code with 32KB buffer: verified from strace data
+
   rv = aIStream->Read(mCopyState->m_dataBuffer + mCopyState->m_leftOver + 1,
                       aLength, &readCount);
   NS_ENSURE_SUCCESS(rv, rv);
   mCopyState->m_leftOver += readCount;
   mCopyState->m_dataBuffer[mCopyState->m_leftOver + 1] = '\0';
   char *start = mCopyState->m_dataBuffer + 1;
   char *endBuffer = mCopyState->m_dataBuffer + mCopyState->m_leftOver + 1;
 
@@ -1980,49 +2084,53 @@ NS_IMETHODIMP nsMsgLocalMailFolder::Copy
       if (mCopyState->m_wholeMsgInStream) {
         end = start + mCopyState->m_leftOver;
         memcpy(end, MSG_LINEBREAK "\0", MSG_LINEBREAK_LEN + 1);
       } else {
         memmove(mCopyState->m_dataBuffer + 1, start, mCopyState->m_leftOver);
         break;
       }
     }
-
     // need to set the linebreak_len each time
     uint32_t linebreak_len = 1;  // assume CR or LF
     if (*end == '\r' && *(end + 1) == '\n') linebreak_len = 2;  // CRLF
 
     if (!mCopyState->m_fromLineSeen) {
       mCopyState->m_fromLineSeen = true;
       NS_ASSERTION(strncmp(start, "From ", 5) == 0,
                    "Fatal ... bad message format\n");
     } else if (strncmp(start, "From ", 5) == 0) {
       // if we're at the beginning of the buffer, we've reserved a byte to
       // insert a '>'.  If we're in the middle, we're overwriting the previous
       // line ending, but we've already written it to m_fileStream, so it's OK.
       *--start = '>';
     }
 
     lineLength = end - start + linebreak_len;
+
+    // This Write should be buffered for performance reasons.
     rv = mCopyState->m_fileStream->Write(start, lineLength, &bytesWritten);
-    if (bytesWritten != lineLength || NS_FAILED(rv)) {
+    if (NS_FAILED(rv) || bytesWritten != lineLength) {
+      NS_WARNING(
+          "rv = mCopyState->m_fileStream->Write(start, lineLength, "
+          "&bytesWritten) failed.");
       ThrowAlertMsg("copyMsgWriteFailed", mCopyState->m_msgWindow);
       mCopyState->m_writeFailed = true;
       return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
     }
 
     if (mCopyState->m_parseMsgState)
       mCopyState->m_parseMsgState->ParseAFolderLine(start, lineLength);
 
     start = end + linebreak_len;
     if (start >= endBuffer) {
       mCopyState->m_leftOver = 0;
       break;
     }
-  }
+  }  // while (1)
   return rv;
 }
 
 void nsMsgLocalMailFolder::CopyPropertiesToMsgHdr(nsIMsgDBHdr *destHdr,
                                                   nsIMsgDBHdr *srcHdr,
                                                   bool aIsMove) {
   nsresult rv;
   nsCOMPtr<nsIPrefBranch> prefBranch(
@@ -2076,24 +2184,42 @@ void nsMsgLocalMailFolder::CopyHdrProper
   destHdr->SetLabel(label);
 }
 
 NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(bool aCopySucceeded) {
   if (!mCopyState) return NS_OK;
 
   // we are the destination folder for a move/copy
   nsresult rv = aCopySucceeded ? NS_OK : NS_ERROR_FAILURE;
+  nsresult rv2 = NS_OK, rv3 = NS_OK;
 
   if (!aCopySucceeded || mCopyState->m_writeFailed) {
     if (mCopyState->m_fileStream) {
-      if (mCopyState->m_curDstKey != nsMsgKey_None)
-        mCopyState->m_msgStore->DiscardNewMessage(mCopyState->m_fileStream,
-                                                  mCopyState->m_newHdr);
-      mCopyState->m_fileStream->Close();
+      // no longer in this version: nsresult rv3;
+      // bool closed = false;
+      if (mCopyState->m_curDstKey != nsMsgKey_None) {
+        rv2 = mCopyState->m_msgStore->DiscardNewMessage(
+            mCopyState->m_fileStream, mCopyState->m_newHdr);
+        // DiscardNewMessage always closes the 1st argument always and returns
+        // error code in rv2
+        mCopyState->m_fileStream = nullptr;
+        // delayed check of DiscardNewMessage() return value.
+        if (NS_FAILED(rv2))
+          NS_WARNING("mCopyState->m_msgStore->DiscardNewMessage() failed");
+      }
+      // XXX TODO better error processing.
+      // XXX TODO ??? do we have to call mCopyState->m_fileStream->Close() here?
+      // It seems so.
+      if (mCopyState->m_fileStream) {
+        rv3 = mCopyState->m_fileStream->Close();
+        if (NS_FAILED(rv3))
+          NS_WARNING("mCopyState->m_fileStream->Close() failed");
+      }
     }
+    // mCopyState->m_fileStream is nullptr here and so Close() is unnecesary.
 
     if (!mCopyState->m_isMove) {
       // passing true because the messages that have been successfully
       // copied have their corresponding hdrs in place. The message that has
       // failed has been truncated so the msf file and berkeley mailbox
       // are in sync.
       (void)OnCopyCompleted(mCopyState->m_srcSupport, true);
       // enable the dest folder
@@ -2129,21 +2255,60 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndC
       do_QueryInterface(mCopyState->m_fileStream));
   if (seekableStream) {
     seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
     rv = FinishNewLocalMessage(mCopyState->m_fileStream, mCopyState->m_newHdr,
                                mCopyState->m_msgStore,
                                mCopyState->m_parseMsgState);
     if (NS_SUCCEEDED(rv) && mCopyState->m_newHdr)
       mCopyState->m_newHdr->GetMessageKey(&mCopyState->m_curDstKey);
-    if (multipleCopiesFinished)
-      mCopyState->m_fileStream->Close();
-    else
-      mCopyState->m_fileStream->Flush();
-  }
+    if (multipleCopiesFinished) {
+      // mCopyState->m_fileStream can be nullptr in DONT-USE-REUSABLE branch
+      if (mCopyState->m_fileStream) {
+        // We have already closed this stream in FnishNewLocalMessage()
+        mCopyState->m_fileStream = nullptr;  // avoid accessing closed stream
+      } else {
+        // Printing something to error console fails xpcshell test, so commented
+        // out on June, 2017
+#if 0
+        MSG_NS_WARN_IF_FALSE(false, "mCopyState->m_fileStream was null and so Close could not be called.");
+#endif
+        // XXX we do not have to call Close() in this version.
+      }
+    } else {
+      // We are probably still processing a list of messages.
+      // We have just finished processing only one of the messages.
+      if (mCopyState->m_fileStream) {
+#if 1
+        // We may have already closed it and m_fileStream could be nullptr.
+        nsresult rv3 = mCopyState->m_fileStream->Flush();
+        // During testing by using a Linux CIFS server as mail store
+        // from TB on another Linux this Flush() returned error code.
+        if (NS_FAILED(rv3)) {
+          fflush(stdout);
+          fprintf(stderr,
+                  "(debug) Flush() returned  rv3 =0x%" PRIx32 " (%s:%d)\n",
+                  static_cast<uint32_t>(rv3), __FILE__, __LINE__);
+        }
+
+        MSG_NS_WARN_IF_FALSE(NS_SUCCEEDED(rv3),
+                             "mCopyState->m_fileStream->Flush() failed.");
+#endif
+      } else {
+        // Printing something to error console fails in xpcshell test, so
+        // commented out on June, 2017
+#if 0
+        MSG_NS_WARN_IF_FALSE(false, "mCopyState->m_fileStream was already null and so Flush could not be called..");
+#endif
+        // XXX maybe we can record the error in an addtional
+        // XXX we do not have to call Close() in this version.m_* variable.
+      }
+    }
+  }  // if (seekableStream)
+
   // Copy the header to the new database
   if (mCopyState->m_message) {
     //  CopyMessages() goes here, and CopyFileMessages() with metadata to save;
     nsCOMPtr<nsIMsgDBHdr> newHdr;
     if (!mCopyState->m_parseMsgState) {
       if (mCopyState->m_destDB) {
         if (mCopyState->m_newHdr) {
           newHdr = mCopyState->m_newHdr;
@@ -2431,28 +2596,41 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndM
   nsresult rv;
 
   if (localUndoTxn) {
     localUndoTxn->GetMsgWindow(getter_AddRefs(msgWindow));
     localUndoTxn->AddSrcKey(key);
     localUndoTxn->AddDstKey(mCopyState->m_curDstKey);
   }
 
+  // sanity check for dont-use-reusable branch.
+  if (!mCopyState->m_fileStream) {
+    MSG_NS_ERROR("mCopyState->m_fileStream is null.");
+  }
+
   // I think this is always true for online to offline copy
   mCopyState->m_dummyEnvelopeNeeded = true;
   nsCOMPtr<nsISeekableStream> seekableStream =
       do_QueryInterface(mCopyState->m_fileStream, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   seekableStream->Seek(nsISeekableStream::NS_SEEK_END, 0);
   rv = FinishNewLocalMessage(mCopyState->m_fileStream, mCopyState->m_newHdr,
                              mCopyState->m_msgStore,
                              mCopyState->m_parseMsgState);
-  mCopyState->m_fileStream->Close();
+  // FinishNewLocalMessage now closes the stream.
   mCopyState->m_fileStream = nullptr;  // all done with the file stream
 
+  // Check for FinishNewMessage return value should come
+  // after potential Close() if Close() is separated from FinishNewMessage.
+  if (NS_FAILED(rv)) {
+    MOZ_ASSERT(NS_SUCCEEDED(rv),
+               "FinishNewMessage(mCopyState->m_fileStream, "
+               "mCopyState->m_newHdr) failed.");
+  }
+
   // CopyFileMessage() and CopyMessages() from servers other than mailbox
   if (mCopyState->m_parseMsgState) {
     nsCOMPtr<nsIMsgDatabase> msgDb;
     nsCOMPtr<nsIMsgDBHdr> newHdr;
 
     mCopyState->m_parseMsgState->FinishHeader();
 
     rv = mCopyState->m_parseMsgState->GetNewMsgHdr(getter_AddRefs(newHdr));
@@ -2483,27 +2661,38 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndM
                                              // we can't undo w/o the msg db
     }
     mCopyState->m_parseMsgState->Clear();
 
     if (mCopyState->m_listener)  // CopyFileMessage() only
       mCopyState->m_listener->SetMessageKey(mCopyState->m_curDstKey);
   }
 
-  if (mCopyState->m_fileStream) mCopyState->m_fileStream->Flush();
+  if (mCopyState->m_fileStream) {
+    nsresult rv3 = mCopyState->m_fileStream->Flush();
+    if (NS_FAILED(rv3)) NS_WARNING("mCopyState->m_fileStream->Flush() failed;");
+    // XXX TODO Better error processing.  Should we not return rv3 if error?
+    // Error propbagation framework is not quite clear.
+  }
   return NS_OK;
 }
 
 nsresult nsMsgLocalMailFolder::CopyMessagesTo(nsIArray *messages,
                                               nsTArray<nsMsgKey> &keyArray,
                                               nsIMsgWindow *aMsgWindow,
                                               nsIMsgFolder *dstFolder,
                                               bool isMove) {
-  if (!mCopyState) return NS_ERROR_OUT_OF_MEMORY;
-
+  if (!mCopyState) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgLocalMailFolder::CopyMessagesTo: "
+            "!mCopyState. Returning with error immediately.\n");
+#endif
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
   nsresult rv;
 
   nsCOMPtr<nsICopyMessageStreamListener> copyStreamListener =
       do_CreateInstance(NS_COPYMESSAGESTREAMLISTENER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsICopyMessageListener> copyListener(
       do_QueryInterface(dstFolder, &rv));
@@ -2676,17 +2865,22 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Serv
       if (folderScanState.m_uidl) {
         msgPop3Server->AddUidlToMark(folderScanState.m_uidl, mark);
         // remember this pop server in list of servers with msgs deleted
         if (pop3Servers.IndexOfObject(msgPop3Server) == -1)
           pop3Servers.AppendObject(msgPop3Server);
       }
     }
   }
-  if (folderScanState.m_inputStream) folderScanState.m_inputStream->Close();
+  if (folderScanState.m_inputStream) {
+    nsresult rv3 = folderScanState.m_inputStream->Close();
+    if (NS_FAILED(rv3))
+      NS_WARNING("folderScanState.m_inputStream->Close() failed;");
+    folderScanState.m_inputStream = nullptr;  // avoid accessing closed stream
+  }
   // need to do this for all pop3 mail servers that had messages deleted.
   uint32_t serverCount = pop3Servers.Count();
   for (uint32_t index = 0; index < serverCount; index++)
     pop3Servers[index]->MarkMessages();
 
   return rv;
 }
 
@@ -3281,17 +3475,18 @@ nsMsgLocalMailFolder::GetFolderScanState
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::GetUidlFromFolder(nsLocalFolderScanState *aState,
                                         nsIMsgDBHdr *aMsgDBHdr) {
   bool more = false;
   uint32_t size = 0, len = 0;
   const char *accountKey = nullptr;
-  nsresult rv = GetMsgInputStream(aMsgDBHdr, &aState->m_streamReusable,
+  bool reusable;  // throw away
+  nsresult rv = GetMsgInputStream(aMsgDBHdr, &reusable,
                                   getter_AddRefs(aState->m_inputStream));
   aState->m_seekableStream = do_QueryInterface(aState->m_inputStream);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoPtr<nsLineBuffer<char> > lineBuffer(new nsLineBuffer<char>);
   NS_ENSURE_TRUE(lineBuffer, NS_ERROR_OUT_OF_MEMORY);
 
   aState->m_uidl = nullptr;
@@ -3317,19 +3512,26 @@ nsMsgLocalMailFolder::GetUidlFromFolder(
         aState->m_uidl = strstr(aState->m_header.get(), X_UIDL);
         if (aState->m_uidl) {
           aState->m_uidl += X_UIDL_LEN + 2;  // skip UIDL: header
           break;
         }
       }
     }
   }
-  if (!aState->m_streamReusable) {
-    aState->m_inputStream->Close();
+  if (aState->m_inputStream) {
+    nsresult rv3 = aState->m_inputStream->Close();
+    MSG_NS_WARN_IF_FALSE(NS_SUCCEEDED(rv3),
+                         "aState->m_inputStream->Close() failed;");
+    // Ignore the input stream Close() error for the moment. No action other
+    // than warning is required.
     aState->m_inputStream = nullptr;
+  } else {
+    // original code did not assume this case could happen. So warn.
+    MSG_NS_WARNING("aState->m_inputStream was null.");
   }
   lineBuffer = nullptr;
   return rv;
 }
 
 /**
  * Adds a message to the end of the folder, parsing it as it goes, and
  * applying filters, if applicable.
@@ -3348,16 +3550,17 @@ nsMsgLocalMailFolder::AddMessage(const c
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::AddMessageBatch(uint32_t aMessageCount,
                                       const char **aMessages,
                                       nsIArray **aHdrArray) {
   NS_ENSURE_ARG_POINTER(aHdrArray);
 
   nsCOMPtr<nsIMsgIncomingServer> server;
+  nsresult rv1;
   nsresult rv = GetServer(getter_AddRefs(server));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgPluggableStore> msgStore;
   nsCOMPtr<nsIOutputStream> outFileStream;
   nsCOMPtr<nsIMsgDBHdr> newHdr;
 
   rv = server->GetMsgStore(getter_AddRefs(msgStore));
@@ -3369,66 +3572,199 @@ nsMsgLocalMailFolder::AddMessageBatch(ui
 
   bool isLocked;
 
   GetLocked(&isLocked);
   if (isLocked) return NS_MSG_FOLDER_BUSY;
 
   AcquireSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
 
+  // WARNING: We must release semaphore before returning !
+  // We use goto statement here to handle the early error return sequence.
+
   if (NS_SUCCEEDED(rv)) {
     nsCOMPtr<nsIMutableArray> hdrArray =
         do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
+    // NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_FAILED(rv)) {
+      NS_WARNING("|do_CreateInstance(NS_ARRAY_CONTRACTID, &rv)| failed.");
+      goto epilog;
+      // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+      // return rv;
+    }
     for (uint32_t i = 0; i < aMessageCount; i++) {
       RefPtr<nsParseNewMailState> newMailParser = new nsParseNewMailState;
-      NS_ENSURE_TRUE(newMailParser, NS_ERROR_OUT_OF_MEMORY);
+      // NS_ENSURE_TRUE(newMailParser, NS_ERROR_OUT_OF_MEMORY);
+      if (!newMailParser) {
+        NS_WARNING("|newMailParser = new nsParseNewMailState;| failed.");
+        rv = NS_ERROR_OUT_OF_MEMORY;
+        goto epilog;
+        // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+        // return NS_ERROR_OUT_OF_MEMORY;
+      }
       if (!mGettingNewMessages) newMailParser->DisableFilters();
-      bool reusable;
+      // bool reusable;
       rv = msgStore->GetNewMsgOutputStream(this, getter_AddRefs(newHdr),
-                                           &reusable,
                                            getter_AddRefs(outFileStream));
-      NS_ENSURE_SUCCESS(rv, rv);
+      // NS_ENSURE_SUCCESS(rv, rv);
+      if (NS_FAILED(rv)) {
+        NS_WARNING("|msgStore->GetNewMsgOutputStream( omission );| failed.");
+#ifdef DEBUG
+        fprintf(
+            stderr,
+            "(debug) nsMsgLocalMailFolder::AddMessageBatch: "
+            "(debug) msgStore->GetNewMsgOutputStream() failed. rv=0x%" PRIx32
+            "\n",
+            static_cast<uint32_t>(rv));
+#endif
+        goto epilog;
+        // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+        // return rv;
+      }
 
       // Get a msgWindow. Proceed without one, but filter actions to imap
       // folders will silently fail if not signed in and no window for a prompt.
       nsCOMPtr<nsIMsgWindow> msgWindow;
       nsCOMPtr<nsIMsgMailSession> mailSession =
           do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
       if (NS_SUCCEEDED(rv))
-        mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
+        rv = mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
+
+      if (NS_FAILED(rv)) {
+#ifdef DEBUG
+        fprintf(stderr,
+                "(debug) nsMsgLocalMailFolder::AddMessageBatch: "
+                "Could not obtain topmost message window. "
+                "filter actions to imap folders may fail silently!\n:");
+#endif
+      }
 
       rv = newMailParser->Init(rootFolder, this, msgWindow, newHdr,
                                outFileStream);
 
+      if (NS_FAILED(rv)) {
+#ifdef DEBUG
+        fprintf(stderr,
+                "(debug) nsMsgLocalMailFolder::AddMessageBatch: "
+                "newMailParser->Init() failed. rv = 0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv));
+#endif
+        goto epilog;
+        // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+        // return rv;
+      }
+
       uint32_t bytesWritten, messageLen = strlen(aMessages[i]);
-      outFileStream->Write(aMessages[i], messageLen, &bytesWritten);
+      nsresult rv4 =
+          outFileStream->Write(aMessages[i], messageLen, &bytesWritten);
+      if (NS_FAILED(rv4) || messageLen != bytesWritten) {
+        MOZ_ASSERT(NS_SUCCEEDED(rv4) && messageLen == bytesWritten,
+                   "outFileStream->Write(aMessages[i], messageLen, "
+                   "&bytesWritten) failed.");
+#ifdef DEBUG
+        fprintf(stderr,
+                "(debug) nsMsgLocalMailFolder::AddMessageBatch: "
+                "outFileStream->Write failed. rv4 = 0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv4));
+#endif
+        if (NS_FAILED(rv4))
+          rv = rv4;
+        else
+          rv = NS_ERROR_FAILURE;  //  written data length is shorter than
+                                  //  intended.
+        goto epilog;
+        // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+        // return rv;
+      }
+
       newMailParser->BufferInput(aMessages[i], messageLen);
 
-      FinishNewLocalMessage(outFileStream, newHdr, msgStore, newMailParser);
-      outFileStream->Close();
+      rv1 =
+          FinishNewLocalMessage(outFileStream, newHdr, msgStore, newMailParser);
+      if (NS_FAILED(rv1)) {
+#ifdef DEBUG
+        fprintf(stderr,
+                "(debug) In nsMsgLocalMailFolder::AddMessageBatch: "
+                "msgStore->FinishNewMessage() "
+                " returned 0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv1));
+#endif
+        // XXX During error testing. This error path *IS* taken.
+        // There was no error checking before.
+        // Devise a good error recovery.  For now, return the error code and
+        // release the semaphore before return.
+
+        // don't exit before closing the file possibly.
+        // Checking for the return value of FinishNewMessage should
+        // come after potential Close() of the 1st argument and nullifying of
+        // |outFileStream| that stores the file stream reference.
+        // rv = rv1;
+        // break
+      }
+
+      // FinishNewLocalMessage now closes outFileStream always.
       outFileStream = nullptr;
+
+      // delayed processing of the error of FinishNewMessage.
+      if (NS_FAILED(rv1)) {
+        rv = rv1;
+        goto epilog;
+        // ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
+        // return rv;
+      }
+
+      // XXX TODO maybe the epilog label needs to come here???
       newMailParser->OnStopRequest(nullptr, NS_OK);
       newMailParser->EndMsgDownload();
       hdrArray->AppendElement(newHdr);
     }
     hdrArray.forget(aHdrArray);
   }
+
+epilog:
   ReleaseSemaphore(static_cast<nsIMsgLocalMailFolder *>(this));
   return rv;
 }
 
 nsresult nsMsgLocalMailFolder::FinishNewLocalMessage(
     nsIOutputStream *aOutputStream, nsIMsgDBHdr *aNewHdr,
     nsIMsgPluggableStore *aMsgStore, nsParseMailMessageState *aParseMsgState) {
   uint32_t bytesWritten;
-  aOutputStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &bytesWritten);
+
+  // XXX Ensure we don't get interrupted here.
+  // pop3 mail download is single thread as I understand. So it is OK, but
+  // imap (attachment?) download uses an extra thread, etc. BEWARE
+  // XXX  Someone who knows this code ought to verify.
+
+  nsresult rv4 =
+      aOutputStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN, &bytesWritten);
+  if (NS_FAILED(rv4) || MSG_LINEBREAK_LEN != bytesWritten) {
+    MOZ_ASSERT(NS_SUCCEEDED(rv4) && MSG_LINEBREAK_LEN == bytesWritten,
+               "mCopyState->m_fileStream->Write(MSG_LINEBREAK, "
+               "MSG_LINEBREAK_LEN, &bytesWritten) failed.");
+    ThrowAlertMsg("EndCopyFailed", mCopyState->m_msgWindow);
+    mCopyState->m_writeFailed = true;
+    return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
+  }
+
   if (aParseMsgState)
     aParseMsgState->ParseAFolderLine(MSG_LINEBREAK, MSG_LINEBREAK_LEN);
-  return aMsgStore->FinishNewMessage(aOutputStream, aNewHdr);
+
+  nsresult rv = aMsgStore->FinishNewMessage(aOutputStream, aNewHdr);
+
+  // Check the error return of FinishNewMessage.
+  if (NS_FAILED(rv)) {
+    MOZ_ASSERT(NS_SUCCEEDED(rv),
+               "mCopyState->m_msgSTore->FinishNewMessage failed.");
+    // XXX TODO  Devise a better error handling.
+    // We probably do not need an early return. This may be part of a move/copy
+    // of multiple messages. So we have to figure out whether we are at the end
+    // of the multiple mesages or not and act accordingly.
+  }
+  return rv;
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::WarnIfLocalFileTooBig(nsIMsgWindow *aWindow,
                                             int64_t aSpaceRequested,
                                             bool *aTooBig) {
   NS_ENSURE_ARG_POINTER(aTooBig);
 
--- a/mailnews/local/src/nsMailboxProtocol.cpp
+++ b/mailnews/local/src/nsMailboxProtocol.cpp
@@ -129,18 +129,22 @@ nsresult nsMailboxProtocol::Initialize(n
           nsCOMPtr<nsIMsgFolder> folder;
           nsCOMPtr<nsIMsgDBHdr> msgHdr;
           rv = msgUrl->GetMessageHeader(getter_AddRefs(msgHdr));
           if (NS_SUCCEEDED(rv) && msgHdr) {
             rv = msgHdr->GetFolder(getter_AddRefs(folder));
             if (NS_SUCCEEDED(rv) && folder) {
               nsCOMPtr<nsIInputStream> stream;
               int64_t offset = 0;
-              bool reusable = false;
+              bool reusable = false;  // throw away
 
+              // XXX TODO Error recovery
+              // When a error of remote CIFS mount for one's Mail directory is
+              // simulated the following GetMsgInputStream failed. March 15,
+              // 2015
               rv = folder->GetMsgInputStream(msgHdr, &reusable,
                                              getter_AddRefs(stream));
               NS_ENSURE_SUCCESS(rv, rv);
               nsCOMPtr<nsISeekableStream> seekableStream(
                   do_QueryInterface(stream, &rv));
               NS_ENSURE_SUCCESS(rv, rv);
               seekableStream->Tell(&offset);
               // create input stream transport
@@ -373,34 +377,40 @@ NS_IMETHODIMP nsMailboxProtocol::OnStopR
 
   // when on stop binding is called, we as the protocol are done...let's close
   // down the connection releasing all of our interfaces. It's important to
   // remember that this on stop binding call is coming from netlib so they are
   // never going to ping us again with on data available. This means we'll never
   // be going through the Process loop...
 
   if (m_multipleMsgMoveCopyStream) {
-    m_multipleMsgMoveCopyStream->Close();
+    nsresult rv3 = m_multipleMsgMoveCopyStream->Close();
+    if (NS_FAILED(rv3))
+      NS_WARNING("m_multipleMsgMoveCopyStream->Close() failed;");
     m_multipleMsgMoveCopyStream = nullptr;
   }
   nsMsgProtocol::OnStopRequest(request, aStatus);
   return CloseSocket();
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 // End of nsIStreamListenerSupport
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 nsresult nsMailboxProtocol::DoneReadingMessage() {
   nsresult rv = NS_OK;
   // and close the article file if it was open....
 
   if (m_mailboxAction == nsIMailboxUrl::ActionSaveMessageToDisk &&
-      m_msgFileOutputStream)
+      m_msgFileOutputStream) {
     rv = m_msgFileOutputStream->Close();
+    if (NS_FAILED(rv)) NS_WARNING("m_msgFileOutputStream->Close() failed;");
+    // This error code is returned at the end by "return rv";
+    m_msgFileOutputStream = nullptr;  // XXX was missing?
+  }
 
   return rv;
 }
 
 nsresult nsMailboxProtocol::SetupMessageExtraction() {
   // Determine the number of bytes we are going to need to read out of the
   // mailbox url....
   nsCOMPtr<nsIMsgDBHdr> msgHdr;
@@ -601,25 +611,29 @@ int32_t nsMailboxProtocol::ReadMessageRe
       terminator as it is read.
       */
       // mscott - the firstline hack is aimed at making sure we don't write
       // out the dummy header when we are trying to display the message.
       // The dummy header is the From line with the date tag on it.
       if (m_msgFileOutputStream && TestFlag(MAILBOX_MSG_PARSE_FIRST_LINE)) {
         uint32_t count = 0;
         rv = m_msgFileOutputStream->Write(line, PL_strlen(line), &count);
-        if (NS_FAILED(rv)) break;
+        if (NS_FAILED(rv) || PL_strlen(line) != count) {
+          NS_WARNING("Write(line, PL_strlen(line), &count) failed.");
+          break;
+        }
 
-        if (canonicalLineEnding)
+        if (canonicalLineEnding) {
           rv = m_msgFileOutputStream->Write(CRLF, 2, &count);
-        else
+          if (NS_FAILED(rv) || 2 != count) break;
+        } else {
           rv = m_msgFileOutputStream->Write(MSG_LINEBREAK, MSG_LINEBREAK_LEN,
                                             &count);
-
-        if (NS_FAILED(rv)) break;
+          if (NS_FAILED(rv) || MSG_LINEBREAK_LEN != count) break;
+        }
       } else
         SetFlag(MAILBOX_MSG_PARSE_FIRST_LINE);
       PR_Free(line);
     }
     PR_Free(line);
   }
 
   SetFlag(MAILBOX_PAUSE_FOR_READ);  // wait for more data to become available...
--- a/mailnews/local/src/nsMovemailService.cpp
+++ b/mailnews/local/src/nsMovemailService.cpp
@@ -437,25 +437,44 @@ nsresult nsMovemailService::GetNewMail(
       break;
     }
 
     buffer.AppendLiteral(MSG_LINEBREAK);
 
     if (isMore && StringBeginsWith(buffer, NS_LITERAL_CSTRING("From "))) {
       // Finish previous header and message, if any.
       if (newHdr) {
-        outputStream->Flush();
+        nsresult rv3 = outputStream->Flush();
+        if (NS_FAILED(rv3)) NS_WARNING("outputStream->Flush() failed;");
         newMailParser->PublishMsgHeader(nullptr);
         rv = msgStore->FinishNewMessage(outputStream, newHdr);
+        // Note that if FinishNewMessage closes outputstream
+        // (at least Maildir version did) (Bug 1121842, 1122698), then the
+        // optimization attempted by reusable flag (now gone) below would have
+        // been really screwed up since although the code assumes
+        // that the reusable stream is still open in the next loop when
+        // |GetNewMsgOutputStream| below is called, but
+        // FinishNewMessage would have closed it already.
+        // So a non null value would remain in outputStream but
+        // the file associated with it was already closed(!?). Agha!
+        // XXX one more reason FinishNewMessage should not close the stream.
+        // But in reality, Maildir version of GetNewMsgOutputStream ()
+        // does not return reusable stream, and so it was OK (!!!).
+        // How convoluted.
+        // It is commented here to avoid any misunderstanding.
+
+        outputStream = nullptr;
+
+        // Delayed check of FinishNewMessage().
+
         NS_ENSURE_SUCCESS(rv, rv);
         newMailParser->Clear();
       }
-      bool reusable;
+      // bool reusable;
       rv = msgStore->GetNewMsgOutputStream(inbox, getter_AddRefs(newHdr),
-                                           &reusable,
                                            getter_AddRefs(outputStream));
       NS_ENSURE_SUCCESS(rv, rv);
 
       rv = newMailParser->Init(serverFolder, inbox, nullptr, newHdr,
                                outputStream);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     if (!outputStream) {
@@ -482,22 +501,34 @@ nsresult nsMovemailService::GetNewMail(
       buffer.AssignLiteral("X-Mozilla-Status2: 00000000" MSG_LINEBREAK);
       newMailParser->HandleLine(buffer.BeginWriting(), buffer.Length());
       rv = outputStream->Write(buffer.get(), buffer.Length(), &bytesWritten);
       NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && (bytesWritten == buffer.Length()),
                      NS_ERROR_FAILURE);
     }
   }
   if (outputStream) {
-    outputStream->Flush();
+    // bool closed = false;
+    nsresult rv3 = outputStream->Flush();
+    if (NS_FAILED(rv3)) NS_WARNING("outputStream->Flush() failed;");
+
     newMailParser->PublishMsgHeader(nullptr);
     newMailParser->OnStopRequest(nullptr, NS_OK);
+
+    // Before, there was a possible file descriptor leak.
+    // When finishNewMessage failed, this routine returned
+    // without (?) closing the stream.
+    // Unless we are trying to throw away the previous write
+    // or something, we should close this.
+
+    // We now close outputStream always inside FinishNewMessage.
     rv = msgStore->FinishNewMessage(outputStream, newHdr);
+    outputStream = nullptr;
+    // delayed check of FinishNewMessage value.
     NS_ENSURE_SUCCESS(rv, rv);
-    outputStream->Close();
   }
   // Truncate the spool file as we parsed it successfully.
   rv = spoolFile->SetFileSize(0);
   if (NS_FAILED(rv)) {
     Error("movemailCantTruncateSpoolFile",
           NS_ConvertUTF8toUTF16(spoolPath).get());
   }
 
--- a/mailnews/local/src/nsMsgBrkMBoxStore.cpp
+++ b/mailnews/local/src/nsMsgBrkMBoxStore.cpp
@@ -113,17 +113,19 @@ NS_IMETHODIMP nsMsgBrkMBoxStore::CreateF
     if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) &&
         unusedDB) {
       // need to set the folder name
       nsCOMPtr<nsIDBFolderInfo> folderInfo;
       rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo));
       if (NS_SUCCEEDED(rv)) folderInfo->SetMailboxName(safeFolderName);
 
       unusedDB->SetSummaryValid(true);
-      unusedDB->Close(true);
+      nsresult rv3 = unusedDB->Close(true);
+      if (NS_FAILED(rv3)) NS_WARNING("unusedDB->Close() failed;");
+      unusedDB = nullptr;
       aParent->UpdateSummaryTotals(true);
     } else {
       path->Remove(false);
       rv = NS_MSG_CANT_CREATE_FOLDER;
     }
   }
   child.forget(aResult);
   return rv;
@@ -135,16 +137,25 @@ void nsMsgBrkMBoxStore::GetMailboxModPro
                                                 uint32_t *aDate) {
   // We'll simply return 0 on errors.
   *aDate = 0;
   *aSize = 0;
   nsCOMPtr<nsIFile> pathFile;
   nsresult rv = aFolder->GetFilePath(getter_AddRefs(pathFile));
   NS_ENSURE_SUCCESS_VOID(rv);
 
+  //
+  // XXX TODO Handle network errors, etc.
+  // Note GetFileSize() can fail for  virtual folders, too.
+  // But when an error of remote CIFS mount for one's Mail directory
+  // is simulated the following call to GetFileSize failed, too.
+  // March 15, 2015
+  // For now, I have no idea what we should do.
+  // Mercy on those people who store one's profile on remote CIFS
+  // server.
   rv = pathFile->GetFileSize(aSize);
   if (NS_FAILED(rv)) return;  // expected result for virtual folders
 
   PRTime lastModTime;
   rv = pathFile->GetLastModifiedTime(&lastModTime);
   NS_ENSURE_SUCCESS_VOID(rv);
 
   *aDate = (uint32_t)(lastModTime / PR_MSEC_PER_SEC);
@@ -551,28 +562,27 @@ NS_IMETHODIMP nsMsgBrkMBoxStore::CopyFol
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgBrkMBoxStore::GetNewMsgOutputStream(nsIMsgFolder *aFolder,
                                          nsIMsgDBHdr **aNewMsgHdr,
-                                         bool *aReusable,
                                          nsIOutputStream **aResult) {
   NS_ENSURE_ARG_POINTER(aFolder);
   NS_ENSURE_ARG_POINTER(aNewMsgHdr);
-  NS_ENSURE_ARG_POINTER(aReusable);
+  // NS_ENSURE_ARG_POINTER(aReusable);
   NS_ENSURE_ARG_POINTER(aResult);
 
 #ifdef _DEBUG
   NS_ASSERTION(m_streamOutstandingFolder != aFolder, "didn't finish prev msg");
   m_streamOutstandingFolder = aFolder;
 #endif
-  *aReusable = true;
+  // *aReusable = true;
 
   nsresult rv;
   nsCOMPtr<nsIFile> mboxFile;
   rv = aFolder->GetFilePath(getter_AddRefs(mboxFile));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIMsgDatabase> db;
   aFolder->GetMsgDatabase(getter_AddRefs(db));
   if (!db && !*aNewMsgHdr) NS_WARNING("no db, and no message header");
@@ -581,27 +591,59 @@ nsMsgBrkMBoxStore::GetNewMsgOutputStream
   if (!exists) {
     rv = mboxFile->Create(nsIFile::NORMAL_FILE_TYPE, 0600);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCString URI;
   aFolder->GetURI(URI);
   nsCOMPtr<nsISeekableStream> seekable;
+
+  // Note here, m_outputStreams is a hash table (maybe an array) or something
+  // like that in this part of code.
+
   if (m_outputStreams.Get(URI, aResult)) {
     seekable = do_QueryInterface(*aResult, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = seekable->Seek(nsISeekableStream::NS_SEEK_END, 0);
     if (NS_FAILED(rv)) {
       m_outputStreams.Remove(URI);
       NS_RELEASE(*aResult);
     }
   }
   if (!*aResult) {
-    rv = MsgGetFileStream(mboxFile, aResult);
+    rv = MsgNewBufferedFileOutputStream(aResult, mboxFile, PR_WRONLY, 00600);
+#ifdef DEBUG
+    // print pathname for easy analysis of the log on tryserver.
+    nsAutoCString mboxFilePath;
+    // GetNativePath is not available under Windows.
+    // GetNativeTarget is.
+    nsresult rv2 = mboxFile->GetNativeTarget(mboxFilePath);
+    if (NS_SUCCEEDED(rv2)) {
+      fprintf(stderr,
+              "(debug) Creating buffered output stream to mboxFile=<<%s>> in "
+              "nsMsgBrkMBoxStore::GetNewMsgOutputStream in "
+              "nsMsgBrkMBoxStore.cpp;\n",
+              mboxFilePath.Data());
+    } else
+      fprintf(stderr,
+              "(debug) Creating buffered output stream in "
+              "nsMsgBrkMBoxStore::GetNewMsgOutputStream in "
+              "nsMsgBrkMBoxStore.cpp. mboxFile path unknown\n");
+
+    // An error occurred when an |Inbox| directory as opposed to |Inbox| file
+    // existed in the mail store. We should check for errors(!)
+    // 8052000D : 	NS_ERROR_FILE_IS_DIRECTORY
+    if (NS_FAILED(rv)) {
+      fprintf(stderr,
+              "(debug) MsgGetFileStream(mboxFile, aResult); returns error "
+              "rv=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv));
+    }
+#endif
     NS_ASSERTION(NS_SUCCEEDED(rv), "failed opening offline store for output");
     if (NS_FAILED(rv))
       printf("failed opening offline store for %s\n", URI.get());
     NS_ENSURE_SUCCESS(rv, rv);
     seekable = do_QueryInterface(*aResult, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = seekable->Seek(nsISeekableStream::NS_SEEK_END, 0);
     NS_ENSURE_SUCCESS(rv, rv);
@@ -621,42 +663,71 @@ nsMsgBrkMBoxStore::GetNewMsgOutputStream
     (*aNewMsgHdr)->SetStringProperty("storeToken", storeToken);
   }
   return rv;
 }
 
 NS_IMETHODIMP
 nsMsgBrkMBoxStore::DiscardNewMessage(nsIOutputStream *aOutputStream,
                                      nsIMsgDBHdr *aNewHdr) {
-  NS_ENSURE_ARG_POINTER(aOutputStream);
+  nsresult rv = NS_OK;
+  // We no longer need the check on |aOututStream|, and actually it is
+  // incorrect.  |aOutputStream| can be null when the caller passes a
+  // filestream pointer which is set to nullptr during error
+  // processing.
+  // NS_ENSURE_ARG_POINTER(aOutputStream);
   NS_ENSURE_ARG_POINTER(aNewHdr);
 #ifdef _DEBUG
   m_streamOutstandingFolder = nullptr;
 #endif
   uint64_t hdrOffset;
   aNewHdr->GetMessageOffset(&hdrOffset);
-  aOutputStream->Close();
+
+  if (aOutputStream) {
+    // Error of this Close() probably needs to be thrown away since this
+    // is an error path.
+    rv = aOutputStream->Close();
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgBrkMBoxStore::DiscardNewMessage calls "
+            "aOutputStream->Close() = 0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+#endif
+  }
+
   nsCOMPtr<nsIFile> mboxFile;
   nsCOMPtr<nsIMsgFolder> folder;
-  nsresult rv = aNewHdr->GetFolder(getter_AddRefs(folder));
+  rv = aNewHdr->GetFolder(getter_AddRefs(folder));
   NS_ENSURE_SUCCESS(rv, rv);
   rv = folder->GetFilePath(getter_AddRefs(mboxFile));
   NS_ENSURE_SUCCESS(rv, rv);
   return mboxFile->SetFileSize(hdrOffset);
 }
 
 NS_IMETHODIMP
 nsMsgBrkMBoxStore::FinishNewMessage(nsIOutputStream *aOutputStream,
                                     nsIMsgDBHdr *aNewHdr) {
+  nsresult rv = NS_OK;
+
 #ifdef _DEBUG
   m_streamOutstandingFolder = nullptr;
 #endif
-  NS_ENSURE_ARG_POINTER(aOutputStream);
-  //  NS_ENSURE_ARG_POINTER(aNewHdr);
-  return NS_OK;
+  // NS_ENSURE_ARG_POINTER(aOutputStream);
+  // NS_ENSURE_ARG_POINTER(aNewHdr);
+
+  if (aOutputStream) {
+    rv = aOutputStream->Close();
+#if DEBUG
+    fprintf(stderr,
+            "{deubg} nsMsgBrkMBoxStore::FinishNewMessage "
+            "aOutputStream->Close() = 0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+#endif
+  }
+  return rv;
 }
 
 NS_IMETHODIMP
 nsMsgBrkMBoxStore::MoveNewlyDownloadedMessage(nsIMsgDBHdr *aNewHdr,
                                               nsIMsgFolder *aDestFolder,
                                               bool *aResult) {
   NS_ENSURE_ARG_POINTER(aNewHdr);
   NS_ENSURE_ARG_POINTER(aDestFolder);
@@ -673,29 +744,56 @@ nsMsgBrkMBoxStore::GetMsgInputStream(nsI
                                      nsIInputStream **aResult) {
   NS_ENSURE_ARG_POINTER(aMsgFolder);
   NS_ENSURE_ARG_POINTER(aResult);
   NS_ENSURE_ARG_POINTER(aOffset);
 
   // If there is no store token, then we set it to the existing message offset.
   if (aMsgToken.IsEmpty()) {
     uint64_t offset;
+#ifdef DEBUG
+    fprintf(
+        stderr,
+        "(debug) nsMsgBrkMBoxStore::GetMsgInputStream: aMsgToken is empty.\n");
+#endif
     NS_ENSURE_ARG_POINTER(aMsgHdr);
     aMsgHdr->GetMessageOffset(&offset);
     *aOffset = int64_t(offset);
     char storeToken[100];
     PR_snprintf(storeToken, sizeof(storeToken), "%lld", *aOffset);
     aMsgHdr->SetStringProperty("storeToken", storeToken);
   } else
     *aOffset = ParseUint64Str(PromiseFlatCString(aMsgToken).get());
   *aReusable = true;
+  nsCString URI;
   nsCOMPtr<nsIFile> mboxFile;
+  aMsgFolder->GetURI(URI);
   nsresult rv = aMsgFolder->GetFilePath(getter_AddRefs(mboxFile));
   NS_ENSURE_SUCCESS(rv, rv);
-  return NS_NewLocalFileInputStream(aResult, mboxFile);
+  rv = NS_NewLocalFileInputStream(aResult, mboxFile);
+#ifdef DEBUG
+  // Print the file path name for easier failure analysis from the log on
+  // tryserver.
+  if (NS_FAILED(rv)) {
+    nsAutoCString mboxFilePath;
+    // GetNativePath is not available under Windows.
+    // GetNativeTarget is.
+    nsresult rv2 = mboxFile->GetNativeTarget(mboxFilePath);
+    if (NS_SUCCEEDED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgBrkMBoxStore::GetMsgInputStream: "
+              "NS_NewLocalFileInputStream() failed. mboxFile.get()=%s\n",
+              mboxFilePath.Data());
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgBrkMBoxStore::GetMsgInputStream: "
+              "NS_NewLocalFileInputStream() failed. mboxFile path unknown.\n");
+  }
+#endif
+  return rv;
 }
 
 NS_IMETHODIMP nsMsgBrkMBoxStore::DeleteMessages(nsIArray *aHdrArray) {
   return ChangeFlags(aHdrArray, nsMsgMessageFlags::Expunged, true);
 }
 
 NS_IMETHODIMP
 nsMsgBrkMBoxStore::CopyMessages(bool isMove, nsIArray *aHdrArray,
@@ -812,16 +910,17 @@ void nsMsgBrkMBoxStore::SetDBValid(nsIMs
 NS_IMETHODIMP nsMsgBrkMBoxStore::ChangeFlags(nsIArray *aHdrArray,
                                              uint32_t aFlags, bool aSet) {
   NS_ENSURE_ARG_POINTER(aHdrArray);
   nsCOMPtr<nsIOutputStream> outputStream;
   nsCOMPtr<nsISeekableStream> seekableStream;
   int64_t restoreStreamPos;
 
   uint32_t messageCount;
+  nsresult rv1;
   nsresult rv = aHdrArray->GetLength(&messageCount);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!messageCount) return NS_ERROR_INVALID_ARG;
 
   rv = GetOutputStream(aHdrArray, outputStream, seekableStream,
                        restoreStreamPos);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -829,21 +928,55 @@ NS_IMETHODIMP nsMsgBrkMBoxStore::ChangeF
   for (uint32_t i = 0; i < messageCount; i++) {
     msgHdr = do_QueryElementAt(aHdrArray, i, &rv);
     // Seek to x-mozilla-status offset and rewrite value.
     rv = UpdateFolderFlag(msgHdr, aSet, aFlags, outputStream);
     if (NS_FAILED(rv)) {
       NS_WARNING("updateFolderFlag failed");
       break;
     }
+
+    rv1 = outputStream->Flush();
+    if (NS_FAILED(rv1)) {
+      NS_WARNING("Flush after updateFolderFlag inside a loop failed");
+#ifdef DEBUG
+      /* print verbose log for easier error analysis of the log on tryserver */
+      fflush(stdout);
+      fprintf(stderr,
+              "(debug) %s:%d: outputStream->Flush() inside a loop returned "
+              "0x%" PRIx32 "\n",
+              __FILE__, __LINE__, static_cast<uint32_t>(rv1));
+#endif
+      break;
+    }
   }
+
+  //
+  // Note that  flush() is done inside the loop, but
+  // if updateFolderFlag itself fails for some reason, we need flushing.
+  //
+  rv1 = outputStream->Flush();
+#ifdef DEBUG
+  fflush(stdout);
+  fprintf(stderr,
+          "(debug) %s:%d: outputStream->Flush() returned 0x%" PRIx32 "\n",
+          __FILE__, __LINE__, static_cast<uint32_t>(rv1));
+#endif
+
+  if (NS_FAILED(rv1)) {
+    NS_WARNING("Flush after updateFolderFlag loop failed");
+  }
+
   if (restoreStreamPos != -1)
     seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, restoreStreamPos);
-  else if (outputStream)
-    outputStream->Close();
+  else if (outputStream) {
+    nsresult rv3 = outputStream->Close();
+    if (NS_FAILED(rv3)) NS_WARNING("outputStream->Close() failed;");
+    outputStream = nullptr;  // code uniformity.
+  }
   if (messageCount > 0) {
     msgHdr = do_QueryElementAt(aHdrArray, 0);
     SetDBValid(msgHdr);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgBrkMBoxStore::ChangeKeywords(nsIArray *aHdrArray,
@@ -893,22 +1026,34 @@ NS_IMETHODIMP nsMsgBrkMBoxStore::ChangeK
     uint64_t messageOffset;
     msgHdr->GetMessageOffset(&messageOffset);
     uint32_t statusOffset = 0;
     (void)msgHdr->GetStatusOffset(&statusOffset);
     uint64_t desiredOffset = messageOffset + statusOffset;
 
     ChangeKeywordsHelper(msgHdr, desiredOffset, lineBuffer, keywordArray, aAdd,
                          outputStream, seekableStream, inputStream);
+    // XXX Detect I/O error ASAP
+    nsresult rv2 = outputStream->Flush();
+#ifdef DEBUG
+    fflush(stdout);
+    fprintf(stderr,
+            "(debug) %s:%d: outputStream->Flush() returned 0x%" PRIx32 "\n",
+            __FILE__, __LINE__, static_cast<uint32_t>(rv2));
+#endif
+    if (NS_FAILED(rv2)) NS_WARNING("outputStream->Flush(); failed.");
   }
   lineBuffer = nullptr;
   if (restoreStreamPos != -1)
     seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, restoreStreamPos);
-  else if (outputStream)
-    outputStream->Close();
+  else if (outputStream) {
+    nsresult rv3 = outputStream->Close();
+    if (NS_FAILED(rv3)) NS_WARNING("outputStream->Close() failed.");
+    outputStream = nullptr;
+  }
   if (messageCount > 0) {
     msgHdr = do_QueryElementAt(aHdrArray, 0);
     SetDBValid(msgHdr);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgBrkMBoxStore::GetStoreType(nsACString &aType) {
--- a/mailnews/local/src/nsMsgLocalStoreUtils.cpp
+++ b/mailnews/local/src/nsMsgLocalStoreUtils.cpp
@@ -84,27 +84,45 @@ void nsMsgLocalStoreUtils::ChangeKeyword
   for (uint32_t i = 0; i < keywordArray.Length(); i++) {
     nsAutoCString header;
     nsAutoCString keywords;
     bool done = false;
     uint32_t len = 0;
     nsAutoCString keywordToWrite(" ");
 
     keywordToWrite.Append(keywordArray[i]);
+
+    // XXX TODO There will be an implicit flush before seek.
+    // We may want to explicitly call it so that a detailed error breakdown can
+    // be done.
+#if 0
+    // Not done currently.
+    nsresult rv1 =  fileStream->Flush();
+    NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "fileStream->Flush() failed.");
+#endif
+
+    // XXX TODO: We ought to check for Seek failure, too...
+    // This may happen if a remote file system failure occurs when Maildir is
+    // on such a remote file system. An error after a timeout will return!
+    // Due to man-power shortage, it is on a todo/fixme for a future work.
+
     seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, desiredOffset);
     // need to reset lineBuffer, which is cheaper than creating a new one.
     lineBuffer->start = lineBuffer->end = lineBuffer->buf;
     bool inKeywordHeader = false;
     bool foundKeyword = false;
     int64_t offsetToAddKeyword = 0;
     bool more;
     message->GetMessageSize(&len);
     // loop through
     while (!done) {
       int64_t lineStartPos;
+      // XXX TODO We ought to check for Tell failure, too...
+      // This may happen if a remote file system failure occurs when Maildir is
+      // on such a remote file system. An error after a timeout will return!
       seekableStream->Tell(&lineStartPos);
       // we need to adjust the linestart pos by how much extra the line
       // buffer has read from the stream.
       lineStartPos -= (lineBuffer->end - lineBuffer->start);
       // NS_ReadLine doesn't return line termination chars.
       nsCString keywordHeaders;
       nsresult rv = NS_ReadLine(inputStream, lineBuffer, keywordHeaders, &more);
       if (NS_SUCCEEDED(rv)) {
@@ -126,19 +144,34 @@ void nsMsgLocalStoreUtils::ChangeKeyword
         if (MsgFindKeyword(keywordArray[i], keywordHeaders, &startOffset,
                            &keywordLength)) {
           foundKeyword = true;
           if (!aAdd)  // if we're removing, remove it, and break;
           {
             keywordHeaders.Cut(startOffset, keywordLength);
             for (int32_t j = keywordLength; j > 0; j--)
               keywordHeaders.Append(' ');
+
+            // we call Flush before seek so that a detailed error breakdown can
+            // be done.
+
+            nsresult rv2 = outputStream->Flush();
+            if (NS_FAILED(rv2)) {
+              NS_WARNING("outputStream->Flush() failed.");
+            }
+            // XXX we ought to check for Seek failure, too...
             seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, lineStartPos);
-            outputStream->Write(keywordHeaders.get(), keywordHeaders.Length(),
-                                &bytesWritten);
+            nsresult rv4 = outputStream->Write(
+                keywordHeaders.get(), keywordHeaders.Length(), &bytesWritten);
+            if (NS_FAILED(rv4) || keywordHeaders.Length() != bytesWritten) {
+              MOZ_ASSERT(
+                  NS_SUCCEEDED(rv4) && keywordHeaders.Length() == bytesWritten,
+                  "outputStream->Write(keywordHeaders.get(), ...) failed.");
+              // XXX better error handling.
+            }
           }
           offsetToAddKeyword = 0;
           // if adding and we already have the keyword, done
           done = true;
           break;
         }
         // argh, we need to check all the lines to see if we already have the
         // keyword, but if we don't find it, we want to remember the line and
@@ -153,20 +186,37 @@ void nsMsgLocalStoreUtils::ChangeKeyword
             offsetToAddKeyword = lineStartPos + curKeywordHdr.Length();
         }
       }
     }
     if (aAdd && !foundKeyword) {
       if (!offsetToAddKeyword)
         message->SetUint32Property("growKeywords", 1);
       else {
+        // This seek is for write.
+        // XXX TODO There will be an implicit flush before seek.
+        // We may want to explicitly call it so that a detailed error breakdown
+        // can be done.
+#if 0
+        // Not done currently.
+        nsresult rv1 =  fileStream->Flush();
+        NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "fileStream->Flush() failed.");
+#endif
+
+        // XXX we ought to check for Seek failure, too...
         seekableStream->Seek(nsISeekableStream::NS_SEEK_SET,
                              offsetToAddKeyword);
-        outputStream->Write(keywordToWrite.get(), keywordToWrite.Length(),
-                            &bytesWritten);
+        nsresult rv4 = outputStream->Write(
+            keywordToWrite.get(), keywordToWrite.Length(), &bytesWritten);
+        if (NS_FAILED(rv4) || keywordToWrite.Length() != bytesWritten) {
+          MOZ_ASSERT(
+              NS_SUCCEEDED(rv4) && keywordToWrite.Length() == bytesWritten,
+              "outputStream->Write(keywordToWrite.get(), ...) failed.");
+          // XXX better error recovery
+        }
       }
     }
   }
 }
 
 nsresult nsMsgLocalStoreUtils::UpdateFolderFlag(nsIMsgDBHdr *mailHdr, bool bSet,
                                                 nsMsgMessageFlagType flag,
                                                 nsIOutputStream *fileStream) {
@@ -177,18 +227,29 @@ nsresult nsMsgLocalStoreUtils::UpdateFol
   // we just ignore this.
   if (NS_FAILED(rv) || (statusOffset == 0)) return NS_OK;
   rv = mailHdr->GetMessageOffset(&msgOffset);
   NS_ENSURE_SUCCESS(rv, rv);
   uint64_t statusPos = msgOffset + statusOffset;
   nsCOMPtr<nsISeekableStream> seekableStream(
       do_QueryInterface(fileStream, &rv));
   NS_ENSURE_SUCCESS(rv, rv);
+
+  // Is the following seek for read/write?
+  // XXX TODO Here will be an implicit flush before seek if we are writing,
+  // We may want to explicitly call it so that a detailed error breakdown can be
+  // done.
+#if 0
+  // Not done currently.
+  nsresult rv1 =  fileStream->Flush();
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "fileStream->Flush() failed.");
+#endif
   rv = seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, statusPos);
   NS_ENSURE_SUCCESS(rv, rv);
+
   char buf[50];
   buf[0] = '\0';
   nsCOMPtr<nsIInputStream> inputStream = do_QueryInterface(fileStream, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   uint32_t bytesRead;
   if (NS_SUCCEEDED(
           inputStream->Read(buf, X_MOZILLA_STATUS_LEN + 6, &bytesRead))) {
     buf[bytesRead] = '\0';
@@ -210,45 +271,87 @@ nsresult nsMsgLocalStoreUtils::UpdateFol
                 (curFlags & ~nsMsgMessageFlags::RuntimeOnly);
         if (bSet)
           flags |= flag;
         else
           flags &= ~flag;
       } else {
         flags &= ~nsMsgMessageFlags::RuntimeOnly;
       }
+
+      // This seek is for write.
+      // XXX TODO There will be an implicit flush before seek.
+      // We may want to explicitly call it so that a detailed error breakdown
+      // can be done.
+#if 0
+      // Not done currently done.
+      nsresult rv1 =  fileStream->Flush();
+      NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "fileStream->Flush() failed.");
+#endif
+
+      // XXX we ought to check for Seek failure, too...
       seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, statusPos);
       // We are filing out x-mozilla-status flags here
       PR_snprintf(buf, sizeof(buf), X_MOZILLA_STATUS_FORMAT,
                   flags & 0x0000FFFF);
       int32_t lineLen = PL_strlen(buf);
       uint64_t status2Pos = statusPos + lineLen;
-      fileStream->Write(buf, lineLen, &bytesWritten);
+      nsresult rv4 = fileStream->Write(buf, lineLen, &bytesWritten);
+      if (NS_FAILED(rv4) || lineLen != (int)bytesWritten) {
+        MOZ_ASSERT(NS_SUCCEEDED(rv4) && lineLen == (int)bytesWritten,
+                   "fileStream->Write(buf, lineLen, &bytesWritten);");
+        // XXX Better error recovery.
+      }
 
       if (flag & 0xFFFF0000) {
+        // The following seek is for read.
+        // XXX TODO We ought to check for Seek failure, too...
+
         // Time to update x-mozilla-status2,
         // first find it by finding end of previous line, see bug 234935.
         seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos);
         do {
           rv = inputStream->Read(buf, 1, &bytesRead);
           status2Pos++;
         } while (NS_SUCCEEDED(rv) && (*buf == '\n' || *buf == '\r'));
         status2Pos--;
+
+        // This seek is for read.
+        // XXX TODO We ought to check for Seek failure, too...
         seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos);
         if (NS_SUCCEEDED(inputStream->Read(buf, X_MOZILLA_STATUS2_LEN + 10,
                                            &bytesRead))) {
           if (strncmp(buf, X_MOZILLA_STATUS2, X_MOZILLA_STATUS2_LEN) == 0 &&
               strncmp(buf + X_MOZILLA_STATUS2_LEN, ": ", 2) == 0 &&
               strlen(buf) >= X_MOZILLA_STATUS2_LEN + 10) {
             uint32_t dbFlags;
             (void)mailHdr->GetFlags(&dbFlags);
             dbFlags &= 0xFFFF0000;
+
+            // The following seek is for write.
+            // XXX TODO There will be an implicit flush before seek.
+            // We may want to explicitly call it so that a detailed error
+            // breakdown can be done.
+#if 0
+            // Currently not done.
+            nsresult rv1 =  fileStream->Flush();
+            NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "fileStream->Flush() failed.");
+#endif
+
+            // XXX we ought to check for Seek failure, too...
             seekableStream->Seek(nsISeekableStream::NS_SEEK_SET, status2Pos);
             PR_snprintf(buf, sizeof(buf), X_MOZILLA_STATUS2_FORMAT, dbFlags);
-            fileStream->Write(buf, PL_strlen(buf), &bytesWritten);
+            nsresult rv4 =
+                fileStream->Write(buf, PL_strlen(buf), &bytesWritten);
+            if (NS_FAILED(rv4) || PL_strlen(buf) != bytesWritten) {
+              MOZ_ASSERT(NS_SUCCEEDED(rv4) && PL_strlen(buf) == bytesWritten,
+                         "fileStream->Write(buf, PL_strlen(buf), "
+                         "&bytesWritten) failed");
+              // XXX better error recovery
+            }
           }
         }
       }
     } else {
 #ifdef DEBUG
       printf(
           "Didn't find %s where expected at position %ld\n"
           "instead, found %s.\n",
--- a/mailnews/local/src/nsMsgMaildirStore.cpp
+++ b/mailnews/local/src/nsMsgMaildirStore.cpp
@@ -238,17 +238,19 @@ NS_IMETHODIMP nsMsgMaildirStore::CreateF
     if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) &&
         unusedDB) {
       // need to set the folder name
       nsCOMPtr<nsIDBFolderInfo> folderInfo;
       rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo));
       if (NS_SUCCEEDED(rv)) folderInfo->SetMailboxName(safeFolderName);
 
       unusedDB->SetSummaryValid(true);
-      unusedDB->Close(true);
+      nsresult rv3 = unusedDB->Close(true);
+      if (NS_FAILED(rv3)) NS_WARNING("unusedDB->Close() failed.");
+      unusedDB = nullptr;
       aParent->UpdateSummaryTotals(true);
     } else {
       MOZ_LOG(MailDirLog, mozilla::LogLevel::Info,
               ("CreateFolder - failed creating db for new folder"));
       path->Remove(true);  // recursive
       rv = NS_MSG_CANT_CREATE_FOLDER;
     }
   }
@@ -554,28 +556,25 @@ NS_IMETHODIMP nsMsgMaildirStore::CopyFol
     }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgMaildirStore::GetNewMsgOutputStream(nsIMsgFolder *aFolder,
                                          nsIMsgDBHdr **aNewMsgHdr,
-                                         bool *aReusable,
                                          nsIOutputStream **aResult) {
   NS_ENSURE_ARG_POINTER(aFolder);
   NS_ENSURE_ARG_POINTER(aNewMsgHdr);
-  NS_ENSURE_ARG_POINTER(aReusable);
   NS_ENSURE_ARG_POINTER(aResult);
 
-  *aReusable = false;  // message per file
-
   nsCOMPtr<nsIMsgDatabase> db;
   nsresult rv = aFolder->GetMsgDatabase(getter_AddRefs(db));
   NS_ENSURE_SUCCESS(rv, rv);
+  if (!db) NS_ERROR("no db");
 
   if (!*aNewMsgHdr) {
     rv = db->CreateNewHdr(nsMsgKey_None, aNewMsgHdr);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   // With maildir, messages have whole file to themselves.
   (*aNewMsgHdr)->SetMessageOffset(0);
 
@@ -612,20 +611,50 @@ nsMsgMaildirStore::GetNewMsgOutputStream
   (*aNewMsgHdr)->SetStringProperty("storeToken", newName.get());
   return MsgNewBufferedFileOutputStream(aResult, newFile,
                                         PR_WRONLY | PR_CREATE_FILE, 00600);
 }
 
 NS_IMETHODIMP
 nsMsgMaildirStore::DiscardNewMessage(nsIOutputStream *aOutputStream,
                                      nsIMsgDBHdr *aNewHdr) {
-  NS_ENSURE_ARG_POINTER(aOutputStream);
+  // We no longer need the check on |aOutputStream|, and actually it
+  // is incorrect.  |aOutputStream| can be null when the caller passes
+  // a filestream pointer which is set to nullptr during error
+  // processing.
+  // NS_ENSURE_ARG_POINTER(aOutputStream);
+
   NS_ENSURE_ARG_POINTER(aNewHdr);
 
-  aOutputStream->Close();
+  // In the design scheme when |reusableflag| is used to
+  // keep openstream unclosed as much as possible,
+  // DiscardNewMessage() should not close aOutputStream usually, but
+  // Maildir version is special.
+  // In a symmetrical or synchronized semantics with FinishNewMessage() it
+  // should close the file stream. This is necessary for Windows. If we keep the
+  // stream opened during DiscardNewMessage(), necessary file removal at the end
+  // cannot be done under Windows.
+  // See bug 1121842
+
+  if (aOutputStream) {  // aOutputStream can be nullptr due to error processing.
+    // Error here probably can be thrown away since this is an error path.
+    nsresult rv1 = aOutputStream->Close();
+    if (NS_FAILED(rv1))
+      NS_WARNING(
+          "nsMsgMaildirStore::DiscardNewMessage: "
+          "aOutputStream->Close() failed.");
+  }
+
+  // XXX not sure what the best error notification/recovery should be.
+  // Failure to close is bad. But at least let us try if we can remove
+  // the file in the subsequent step. This SHOULD WORK under
+  // Linux and OSX even if Close() fails here (eventually at the time of
+  // TB exit, the file should disappear since no reference to it
+  // will be maintained then.).
+
   // file path is stored in message header property "storeToken"
   nsAutoCString fileName;
   aNewHdr->GetStringProperty("storeToken", getter_Copies(fileName));
   if (fileName.IsEmpty()) return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIFile> path;
   nsCOMPtr<nsIMsgFolder> folder;
   nsresult rv = aNewHdr->GetFolder(getter_AddRefs(folder));
@@ -638,48 +667,129 @@ nsMsgMaildirStore::DiscardNewMessage(nsI
   path->AppendNative(fileName);
 
   return path->Remove(false);
 }
 
 NS_IMETHODIMP
 nsMsgMaildirStore::FinishNewMessage(nsIOutputStream *aOutputStream,
                                     nsIMsgDBHdr *aNewHdr) {
-  NS_ENSURE_ARG_POINTER(aOutputStream);
+  // XXX What would be the proper error handling if Close() fails.
+  //     We don't even tell the error to the user today.
+
+  // aOutputStream can be nullptr due to error processing.
+  // NS_ENSURE_ARG_POINTER(aOutputStream);
+#ifdef DEBUG
+  // Let us check if this strange situation can happen for DEBUG binary.
+  if (!aOutputStream) {
+    fprintf(stderr,
+            "(debug) aOutputStream is nullptr on entry to "
+            "nsMsgMaildirStore::FinishNewMessage\n");
+  }
+#endif
+
   NS_ENSURE_ARG_POINTER(aNewHdr);
 
-  aOutputStream->Close();
+  // In the design scheme when |reusableflag| is used to
+  // keep openstream unclosed as much as possible,
+  // FinishNewMessage() should not close aOutputStream usually, but
+  // Maildir version is special.
+  // In a symmetrical or synchronized semantics with DiscardNewMessage() it
+  // should close the file stream. This is necessary for Windows. If we keep the
+  // stream opened during FinishNewMessage(), necessary file move/copy between
+  // "cur" and "tmp" cannot be done under Windows. See bug 1121842
+
+  if (aOutputStream) {  // aOutputStream can be nullptr due to error processing.
+    nsresult rv1 = aOutputStream->Close();
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "aOutputStream(%p)->Close() = 0x%" PRIx32 "\n",
+            aOutputStream, static_cast<uint32_t>(rv1));
+#endif
+    if (NS_FAILED(rv1))
+      NS_WARNING(
+          "nsMsgMaildirStore::FinishNewMessage: "
+          "aOutputStream->Close() failed.");
+  }
+  // Failure to close is bad. But at least let us try proceeding.
+  // Even if close fails, the following processing should work under Linux and
+  // OSX.
 
   nsCOMPtr<nsIFile> folderPath;
   nsCOMPtr<nsIMsgFolder> folder;
   nsresult rv = aNewHdr->GetFolder(getter_AddRefs(folder));
+#ifdef DEBUG
+  if (NS_FAILED(rv)) {
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "aNewHdr->GetFolder failed rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+  }
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
   rv = folder->GetFilePath(getter_AddRefs(folderPath));
+#ifdef DEBUG
+  if (NS_FAILED(rv)) {
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "folder->GetFilePath failed rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+  }
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
 
   // tmp filename is stored in "storeToken".
   // By now we'll have the Message-ID, which we'll base the final filename on.
   nsAutoCString tmpName;
   aNewHdr->GetStringProperty("storeToken", getter_Copies(tmpName));
   if (tmpName.IsEmpty()) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "no storeToken in msg hdr!!\n");
+#endif
     NS_ERROR("FinishNewMessage - no storeToken in msg hdr!!");
     return NS_ERROR_FAILURE;
   }
 
   // path to the new destination
   nsCOMPtr<nsIFile> curPath;
   folderPath->Clone(getter_AddRefs(curPath));
   curPath->Append(NS_LITERAL_STRING("cur"));
 
   // let's check if the folder exists
   // XXX TODO: kill this and make sure maildir creation includes cur/tmp
   bool exists;
   curPath->Exists(&exists);
   if (!exists) {
     rv = curPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    nsAutoCString nativePath;
+    if (NS_FAILED(rv)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "curPath->Create failed. rv=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv));
+      // GetNativePath is not available under Windows.
+      // GetNativeTarget is.
+      nsresult rv2 = curPath->GetNativeTarget(nativePath);
+      if (NS_FAILED(rv2)) {
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::FinishNewMessage: "
+                "curPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv2));
+      } else
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+                "curPath->nativePath = <<%s>>\n",
+                nativePath.Data());
+    }
+#endif
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // path to the downloaded message
   nsCOMPtr<nsIFile> fromPath;
   folderPath->Clone(getter_AddRefs(fromPath));
   fromPath->Append(NS_LITERAL_STRING("tmp"));
   fromPath->AppendNative(tmpName);
@@ -688,25 +798,74 @@ nsMsgMaildirStore::FinishNewMessage(nsIO
   // XXX TODO: revisit this. I think it's needed because the
   // pairing rules for:
   // GetNewMsgOutputStream(), FinishNewMessage(),
   // MoveNewlyDownloadedMessage() and DiscardNewMessage()
   // are not well defined.
   // If they are sorted out, this code can be removed.
   fromPath->Exists(&exists);
   if (!exists) {
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "fromPath does NOT exist?!\n");
+    nsresult rv2 = fromPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "fromPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "fromPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+#endif
     // Perhaps the message has already moved. See bug 1028372 to fix this.
     nsCOMPtr<nsIFile> existingPath;
     curPath->Clone(getter_AddRefs(existingPath));
     existingPath->AppendNative(tmpName);
     existingPath->Exists(&exists);
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    {
+      fprintf(stderr, "(debug) checking existingPath.\n");
+      nsAutoCString nativePath;
+      nsresult rv2 = existingPath->GetNativeTarget(nativePath);
+      if (NS_FAILED(rv2)) {
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::FinishNewMessage: "
+                "existingPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv2));
+      } else {
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::FinishNewMsg: "
+                "existingPath->nativePath = <<%s>>\n",
+                nativePath.Data());
+      }
+    }
+#endif
     if (exists)  // then there is nothing to do
+    {
+#ifdef DEBUG
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "cur? does NOT exist, but existingPath exists. So it is OK\n");
+#endif
       return NS_OK;
+    }
 
-    NS_ERROR("FinishNewMessage - oops! file does not exist!");
+    // We hit this path during xpcshell-test of windows binary on tryserver
+    // when we experimented with enabling buffered write.
+    // NS_ERROR was a little too severe.
+    // NS_ERROR("FinishNewMessage - oops! file does not exist!");
+    //
+    NS_WARNING("FinishNewMessage - oops! existingPath does not exist!");
     return NS_ERROR_FILE_TARGET_DOES_NOT_EXIST;
   }
 
   nsCString msgID;
   aNewHdr->GetMessageId(getter_Copies(msgID));
 
   nsCString baseName;
   // For missing or suspiciously-short Message-IDs, use a timestamp
@@ -728,16 +887,37 @@ nsMsgMaildirStore::FinishNewMessage(nsIO
   nsCOMPtr<nsIFile> toPath;
   curPath->Clone(getter_AddRefs(toPath));
   nsCString toName(baseName);
   toName.Append(".eml");
   toPath->AppendNative(toName);
 
   // Using CreateUnique in case we have duplicate Message-Ids
   rv = toPath->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+#ifdef DEBUG
+  // print pathnames for easy analysis of the log file on tryserver.
+  if (NS_FAILED(rv)) {
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "toPath->CreateUnique failed. rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+    nsresult rv2 = toPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "toPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+              "toPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+  }
+#endif
   if (NS_FAILED(rv)) {
     // NS_ERROR_FILE_TOO_BIG means CreateUnique() bailed out at 10000 attempts.
     if (rv != NS_ERROR_FILE_TOO_BIG) {
       NS_ENSURE_SUCCESS(rv, rv);
     }
     // As a last resort, fall back to using timestamp as filename.
     toName.SetLength(0);
     toName.AppendInt(static_cast<int64_t>(PR_Now()));
@@ -745,16 +925,54 @@ nsMsgMaildirStore::FinishNewMessage(nsIO
     toPath->SetNativeLeafName(toName);
     rv = toPath->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Move into place (using whatever name CreateUnique() settled upon).
   toPath->GetNativeLeafName(toName);
   rv = fromPath->MoveToNative(curPath, toName);
+#ifdef DEBUG
+  // print pathnames for easy analysis of the log file on tryserver.
+  if (NS_FAILED(rv)) {
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::FinishNewMessage: "
+            "fromPath->MoveToNative(curPath, toName); failed. rv=0x%" PRIx32
+            "\n",
+            static_cast<uint32_t>(rv));
+    // print fromPath, toPath, fileName
+    // fromPath
+    nsresult rv2 = fromPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "fromPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "fromPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+    // toPath
+    rv2 = toPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::FinishNewMessage: "
+              "toPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+              "toPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+    // fileName
+    fprintf(stderr, "(debug) fileName = <<%s>>\n", nativePath.Data());
+  }
+#endif
   NS_ENSURE_SUCCESS(rv, rv);
   // Update the db to reflect the final filename.
   aNewHdr->SetStringProperty("storeToken", toName.get());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgMaildirStore::MoveNewlyDownloadedMessage(nsIMsgDBHdr *aHdr,
@@ -763,91 +981,248 @@ nsMsgMaildirStore::MoveNewlyDownloadedMe
   NS_ENSURE_ARG_POINTER(aHdr);
   NS_ENSURE_ARG_POINTER(aDestFolder);
   NS_ENSURE_ARG_POINTER(aResult);
 
   nsCOMPtr<nsIFile> folderPath;
   nsCOMPtr<nsIMsgFolder> folder;
   nsresult rv = aHdr->GetFolder(getter_AddRefs(folder));
   NS_ENSURE_SUCCESS(rv, rv);
+  if (!folder) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: folder was "
+            "NULL!.\n");
+#endif
+    return NS_ERROR_FAILURE;
+  }
   rv = folder->GetFilePath(getter_AddRefs(folderPath));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  if (!folderPath) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: folderPath "
+            "was NULL!.\n");
+#endif
+    return NS_ERROR_FAILURE;
+  }
+
   // file path is stored in message header property
   nsAutoCString fileName;
   aHdr->GetStringProperty("storeToken", getter_Copies(fileName));
   if (fileName.IsEmpty()) {
-    NS_ERROR("FinishNewMessage - no storeToken in msg hdr!!");
+    // We hit this path during xpcshell-test of windows binary on tryserver.
+    // NS_ERROR was a little too severe.
+    NS_WARNING("MoveNewlyDownloadedMessage - oops! no filename in storeToken!");
     return NS_ERROR_FAILURE;
   }
 
   // path to the downloaded message
   nsCOMPtr<nsIFile> fromPath;
   folderPath->Clone(getter_AddRefs(fromPath));
+  if (!fromPath) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: fromPath "
+            "was NULL!.\n");
+#endif
+    return NS_ERROR_FAILURE;
+  }
   fromPath->Append(NS_LITERAL_STRING("cur"));
   fromPath->AppendNative(fileName);
 
   // let's check if the tmp file exists
-  bool exists;
+  bool exists = false;
   fromPath->Exists(&exists);
   if (!exists) {
-    NS_ERROR("FinishNewMessage - oops! file does not exist!");
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    nsAutoCString nativePath;
+    nsresult rv2 = fromPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) fromPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "fromPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+#endif
+    // We hit this path during xpcshell-test of windows binary on tryserver.
+    // NS_ERROR was a little too severe.
+    // NS_ERROR("FinishNewMessage - oops! file does not exist!");
+    //
+    NS_WARNING("FinishNewMessage - oops! file does not exist!\n");
     return NS_ERROR_FAILURE;
   }
 
   // move to the "cur" subfolder
   nsCOMPtr<nsIFile> toPath;
   aDestFolder->GetFilePath(getter_AddRefs(folderPath));
+  if (!folderPath) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: folderPath "
+            "was NULL!.\n");
+#endif
+    return NS_ERROR_FAILURE;
+  }
+
   folderPath->Clone(getter_AddRefs(toPath));
+  if (!toPath) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: toPath was "
+            "NULL!.\n");
+#endif
+    return NS_ERROR_FAILURE;
+  }
+
   toPath->Append(NS_LITERAL_STRING("cur"));
 
   // let's check if the folder exists
   // XXX TODO: kill this and make sure maildir creation includes cur/tmp
+  exists = false;
   toPath->Exists(&exists);
   if (!exists) {
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+            "Creating toPath file\n: ");
+    nsresult rv2 = toPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) toPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else {
+      fprintf(stderr, "(debug) toPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+    }
+#endif
+
     rv = toPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
+#ifdef DEBUG
+    if (NS_FAILED(rv)) {
+      fprintf(stderr, "(debug) toPath->Create() failed. rv =0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv));
+    }
+#endif
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIMsgDatabase> destMailDB;
   rv = aDestFolder->GetMsgDatabase(getter_AddRefs(destMailDB));
-  NS_WARNING_ASSERTION(destMailDB && NS_SUCCEEDED(rv),
-                       "failed to open mail db moving message");
+  if (!(destMailDB && NS_SUCCEEDED(rv)))
+    NS_WARNING("failed to open mail db moving message");
 
   nsCOMPtr<nsIMsgDBHdr> newHdr;
   if (destMailDB)
     rv = destMailDB->CopyHdrFromExistingHdr(nsMsgKey_None, aHdr, true,
                                             getter_AddRefs(newHdr));
   if (NS_SUCCEEDED(rv) && !newHdr) rv = NS_ERROR_UNEXPECTED;
 
   if (NS_FAILED(rv)) {
     aDestFolder->ThrowAlertMsg("filterFolderHdrAddFailed", nullptr);
     return rv;
   }
 
   nsCOMPtr<nsIFile> existingPath;
   toPath->Clone(getter_AddRefs(existingPath));
+  if (!existingPath) {
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+            "existingPath was NULL after toPath->Clone()!\n");
+#endif
+  }
   existingPath->AppendNative(fileName);
+  exists = false;
   existingPath->Exists(&exists);
 
   if (exists) {
     rv = existingPath->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    if (NS_FAILED(rv)) {
+      nsAutoCString nativePath;
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "existingPath->CreateUnique failed. rv=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv));
+      nsresult rv2 = existingPath->GetNativeTarget(nativePath);
+      if (NS_FAILED(rv2)) {
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+                "existingPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv2));
+      } else
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+                "existingPath->nativePath = <<%s>>\n",
+                nativePath.Data());
+    }
+#endif
     NS_ENSURE_SUCCESS(rv, rv);
     existingPath->GetNativeLeafName(fileName);
     newHdr->SetStringProperty("storeToken", fileName.get());
   }
 
   rv = fromPath->MoveToNative(toPath, fileName);
+#ifdef DEBUG
+  // print pathnames for easy analysis of the log file on tryserver.
+  if (NS_FAILED(rv)) {
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+            "fromPath->MoveToNative(toPath, fileName); failed. rv=0x%" PRIx32
+            "\n",
+            static_cast<uint32_t>(rv));
+    // print fromPath, toPath, fileName
+    // fromPath
+    nsresult rv2 = fromPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "fromPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "fromPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+    // toPath
+    rv2 = existingPath->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "existingPath->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::MoveNewlyDownloadedMessage: "
+              "existingPath->nativePath = <<%s>>\n",
+              nativePath.Data());
+    // fileName
+    fprintf(stderr, "(debug) fileName = <<%s>>\n", fileName.Data());
+  }
+#endif
   *aResult = NS_SUCCEEDED(rv);
   if (NS_FAILED(rv))
     aDestFolder->ThrowAlertMsg("filterFolderWriteFailed", nullptr);
 
   if (NS_FAILED(rv)) {
-    if (destMailDB) destMailDB->Close(true);
-
+    if (destMailDB) {
+      nsresult rv3 = destMailDB->Close(true);
+      if (NS_FAILED(rv3)) NS_WARNING("destMailDB->Close(true) failed.");
+      destMailDB = nullptr;
+    }
     return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
   }
 
   bool movedMsgIsNew = false;
   // if we have made it this far then the message has successfully been
   // written to the new folder now add the header to the destMailDB.
 
   uint32_t newFlags;
@@ -906,34 +1281,95 @@ nsMsgMaildirStore::GetMsgInputStream(nsI
   // construct path to file
   nsCOMPtr<nsIFile> path;
   nsresult rv = aMsgFolder->GetFilePath(getter_AddRefs(path));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (aMsgToken.IsEmpty()) {
     MOZ_LOG(MailDirLog, mozilla::LogLevel::Info,
             ("GetMsgInputStream - empty storeToken!!"));
+#ifdef DEBUG
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+            "aMsgToken was empty, returning NS_ERROR_FAILURE\n");
+#endif
     return NS_ERROR_FAILURE;
   }
 
   path->Append(NS_LITERAL_STRING("cur"));
 
   // let's check if the folder exists
   // XXX TODO: kill this and make sure maildir creation includes cur/tmp
-  bool exists;
-  path->Exists(&exists);
-  if (!exists) {
+  bool exists = false;
+  rv = path->Exists(&exists);
+#ifdef DEBUG
+  if (NS_FAILED(rv)) {
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+            "path->Exists failed: rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+  }
+#endif
+  if (NS_SUCCEEDED(rv) && !exists) {
     MOZ_LOG(MailDirLog, mozilla::LogLevel::Info,
             ("GetMsgInputStream - oops! cur subfolder does not exist!"));
     rv = path->Create(nsIFile::DIRECTORY_TYPE, 0755);
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    if (NS_FAILED(rv)) {
+      fprintf(
+          stderr,
+          "(debug) nsMsgMaildirStore::GetMsgInputStream: path->Create failed. "
+          "rv=0x%" PRIx32 "\n",
+          static_cast<uint32_t>(rv));
+
+      nsAutoCString nativePath;
+      nsresult rv2 = path->GetNativeTarget(nativePath);
+      if (NS_FAILED(rv2)) {
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+                "path->GetNativeTarget failed. "
+                "rv2=0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv2));
+      } else
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+                "path->nativePath = <<%s>>\n",
+                nativePath.Data());
+    }
+#endif
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   path->AppendNative(aMsgToken);
-  return NS_NewLocalFileInputStream(aResult, path);
+  rv = NS_NewLocalFileInputStream(aResult, path);
+#ifdef DEBUG
+  // print pathnames for easy analysis of the log file on tryserver.
+  if (NS_FAILED(rv)) {
+    nsAutoCString nativePath;
+    fprintf(stderr,
+            "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+            "NS_NewLocalFileInputStream() failed. "
+            "rv=0x%" PRIx32 "\n",
+            static_cast<uint32_t>(rv));
+    nsresult rv2 = path->GetNativeTarget(nativePath);
+    if (NS_FAILED(rv2)) {
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+              "path->GetNativeTarget failed. "
+              "rv2=0x%" PRIx32 "\n",
+              static_cast<uint32_t>(rv2));
+    } else
+      fprintf(stderr,
+              "(debug) nsMsgMaildirStore::GetMsgInputStream: path->nativePath "
+              "= <<%s>>\n",
+              nativePath.Data());
+  }
+#endif
+  return rv;
 }
 
 NS_IMETHODIMP nsMsgMaildirStore::DeleteMessages(nsIArray *aHdrArray) {
   uint32_t messageCount;
   nsresult rv = aHdrArray->GetLength(&messageCount);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIMsgFolder> folder;
 
@@ -953,17 +1389,17 @@ NS_IMETHODIMP nsMsgMaildirStore::DeleteM
       // Perhaps an offline store has not downloaded this particular message.
       continue;
     }
 
     path->Append(NS_LITERAL_STRING("cur"));
     path->AppendNative(fileName);
 
     // Let's check if the message exists.
-    bool exists;
+    bool exists = false;
     path->Exists(&exists);
     if (!exists) {
       MOZ_LOG(MailDirLog, mozilla::LogLevel::Info,
               ("DeleteMessages - file does not exist !!"));
       // Perhaps an offline store has not downloaded this particular message.
       continue;
     }
     path->Remove(false);
@@ -1067,27 +1503,70 @@ nsMsgMaildirStore::CopyMessages(bool aIs
     nsCOMPtr<nsIFile> srcFile;
     rv = srcFolderPath->Clone(getter_AddRefs(srcFile));
     NS_ENSURE_SUCCESS(rv, rv);
     srcFile->AppendNative(fileName);
 
     nsCOMPtr<nsIFile> destFile;
     destFolderPath->Clone(getter_AddRefs(destFile));
     destFile->AppendNative(fileName);
-    bool exists;
+    bool exists = false;
     destFile->Exists(&exists);
     if (exists) {
       rv = destFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
+#ifdef DEBUG
+      // print pathnames for easy analysis of the log file on tryserver.
+      if (NS_FAILED(rv)) {
+        nsAutoCString nativePath;
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::FinishNewMessage: "
+                "destFile->CreateUnique failed. rv=0x%" PRIx32 "\n",
+                static_cast<uint32_t>(rv));
+        nsresult rv2 = destFile->GetNativeTarget(nativePath);
+        if (NS_FAILED(rv2)) {
+          fprintf(stderr,
+                  "(debug) nsMsgMaildirStore::FinishNewMessage: "
+                  "destFile->GetNativeTarget failed. rv2=0x%" PRIx32 "\n",
+                  static_cast<uint32_t>(rv2));
+        } else
+          fprintf(stderr,
+                  "(debug) nsMsgMaildirStore::GetMsgInputStream: "
+                  "destFile->nativePath = <<%s>>\n",
+                  nativePath.Data());
+      }
+#endif
       NS_ENSURE_SUCCESS(rv, rv);
       destFile->GetNativeLeafName(fileName);
     }
     if (aIsMove)
       rv = srcFile->MoveToNative(destFolderPath, fileName);
     else
       rv = srcFile->CopyToNative(destFolderPath, fileName);
+#ifdef DEBUG
+    // print pathnames for easy analysis of the log file on tryserver.
+    if (NS_FAILED(rv)) {
+      nsAutoCString nativePath;
+      fprintf(stderr, "(debug) %s failed. rv = 0x%" PRIx32 "\n",
+              (aIsMove) ? "MoveToNative(destFolderPath, Filename);"
+                        : "CopyToNative(destFolderPath, fileName);",
+              static_cast<uint32_t>(rv));
+      nsresult rv2 = destFolderPath->GetNativeTarget(nativePath);
+      if (NS_FAILED(rv2)) {
+        fprintf(stderr,
+                "(debug) destFolderPath->GetNativeTarget failed. rv2=0x%" PRIx32
+                "\n",
+                static_cast<uint32_t>(rv2));
+      } else
+        fprintf(stderr,
+                "(debug) nsMsgMaildirStore::CopyMessages: "
+                "destFolderPath->nativePath = <<%s>>\n",
+                nativePath.Data());
+      fprintf(stderr, "(debug) fileName = <<%s>>\n", fileName.Data());
+    }
+#endif
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIMsgDBHdr> destHdr;
     if (destDB) {
       rv = destDB->CopyHdrFromExistingHdr(nsMsgKey_None, srcHdr, true,
                                           getter_AddRefs(destHdr));
       NS_ENSURE_SUCCESS(rv, rv);
       destHdr->SetStringProperty("storeToken", fileName.get());
@@ -1293,19 +1772,45 @@ NS_IMETHODIMP nsMsgMaildirStore::ChangeF
   NS_ENSURE_SUCCESS(rv, rv);
 
   for (uint32_t i = 0; i < messageCount; i++) {
     nsCOMPtr<nsIMsgDBHdr> msgHdr = do_QueryElementAt(aHdrArray, i, &rv);
     // get output stream for header
     nsCOMPtr<nsIOutputStream> outputStream;
     rv = GetOutputStream(msgHdr, outputStream);
     NS_ENSURE_SUCCESS(rv, rv);
+
+    // XXX Flush before seek for reporting
+    // possible Flush() error in more detail.
+    // This particular instance may be null operation.
+    // Not currently done.
+    // nsresult rv1 = outputStream->Flush();
+    // NS_WARN_IF_FALSE(NS_SUCCEEDED(rv1), "outputStream->Flush(); failed.");
+
     // Seek to x-mozilla-status offset and rewrite value.
     rv = UpdateFolderFlag(msgHdr, aSet, aFlags, outputStream);
     if (NS_FAILED(rv)) NS_WARNING("updateFolderFlag failed");
+
+    // XXX
+    // CAUTION: watch out for performance regression.
+    // We want to flush after a write in this particular instance.
+    // But we usually want to avoid Flush() as much as possible so
+    // that buffering is effective.
+
+    nsresult rv1 = outputStream->Flush();
+#ifdef DEBUG
+    fflush(stdout);
+    fprintf(stderr,
+            "(debug) : Extra %d: outputStream->Flush() returned in "
+            "nsMsgMaildirStore.cpp "
+            "0x%" PRIx32 "\n",
+            __LINE__, static_cast<uint32_t>(rv1));
+#endif
+
+    if (NS_FAILED(rv1)) NS_WARNING("outputStream->Flush(); failed.");
   }
   return NS_OK;
 }
 
 // get output stream from header
 nsresult nsMsgMaildirStore::GetOutputStream(
     nsIMsgDBHdr *aHdr, nsCOMPtr<nsIOutputStream> &aOutputStream) {
   // file name is stored in message header property "storeToken"
@@ -1360,19 +1865,24 @@ NS_IMETHODIMP nsMsgMaildirStore::ChangeK
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsISeekableStream> seekableStream(
         do_QueryInterface(inputStream, &rv));
     NS_ENSURE_SUCCESS(rv, rv);
     uint32_t statusOffset = 0;
     (void)message->GetStatusOffset(&statusOffset);
     uint64_t desiredOffset = statusOffset;
 
+    // outputStream->Flush() is done inside ChangeKeywordsHelper.
     ChangeKeywordsHelper(message, desiredOffset, lineBuffer, keywordArray, aAdd,
                          outputStream, seekableStream, inputStream);
-    if (inputStream) inputStream->Close();
+    if (inputStream) {
+      nsresult rv3 = inputStream->Close();
+      if (NS_FAILED(rv3)) NS_WARNING("inputStream->Close() failed.");
+      inputStream = nullptr;
+    }
     // ### TODO - if growKeywords property is set on the message header,
     // we need to rewrite the message file with extra room for the keywords,
     // or schedule some sort of background task to do this.
   }
   lineBuffer = nullptr;
   return NS_OK;
 }
 
@@ -1399,17 +1909,17 @@ nsresult nsMsgMaildirStore::CreateDirect
   nsresult rv = NS_OK;
   if (!aIsServer) {
     rv = GetDirectoryForFolder(path);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   bool pathIsDirectory = false;
   path->IsDirectory(&pathIsDirectory);
   if (!pathIsDirectory) {
-    bool pathExists;
+    bool pathExists = false;
     path->Exists(&pathExists);
     // If for some reason there's a file with the directory separator
     // then we are going to fail.
     rv = pathExists ? NS_MSG_COULD_NOT_CREATE_DIRECTORY
                     : path->Create(nsIFile::DIRECTORY_TYPE, 0700);
   }
   return rv;
 }
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -295,16 +295,18 @@ nsresult nsMsgMailboxParser::ProcessMail
   nsresult ret = NS_OK;
 
   uint32_t bytesRead = 0;
 
   if (NS_SUCCEEDED(m_inputStream.GrowBuffer(aLength))) {
     // OK, this sucks, but we're going to have to copy into our
     // own byte buffer, and then pass that to the line buffering code,
     // which means a couple buffer copies.
+    // XXX TODO we should repeat Read until all the bytes are read...
+    // Would be handled by future patch. CI
     ret = aIStream->Read(m_inputStream.GetBuffer(), aLength, &bytesRead);
     if (NS_SUCCEEDED(ret))
       ret = BufferInput(m_inputStream.GetBuffer(), bytesRead);
   }
   if (m_graph_progress_total > 0) {
     if (NS_SUCCEEDED(ret)) m_graph_progress_received += bytesRead;
   }
   return (ret);
@@ -1237,18 +1239,18 @@ nsresult nsParseMailMessageState::Finali
     nsAutoCString rawMsgId;
     /* Take off <> around message ID. */
     if (id) {
       if (id->length > 0 && id->value[0] == '<') {
         id->length--;
         id->value++;
       }
 
-      NS_WARNING_ASSERTION(id->length > 0,
-                           "id->length failure in FinalizeHeaders().");
+      if (id->length <= 0)
+        NS_WARNING("id->length failure in FinalizeHeaders().");
 
       if (id->length > 0 && id->value[id->length - 1] == '>')
         /* generate a new null-terminated string without the final > */
         rawMsgId.Assign(id->value, id->length - 1);
       else
         rawMsgId.Assign(id->value);
     }
 
@@ -1605,18 +1607,28 @@ nsresult nsParseNewMailState::Init(nsIMs
             aMsgWindow, getter_AddRefs(m_deferredToServerFilterList));
     }
   }
   m_disableFilters = false;
   return NS_OK;
 }
 
 nsParseNewMailState::~nsParseNewMailState() {
-  if (m_mailDB) m_mailDB->Close(true);
-  if (m_backupMailDB) m_backupMailDB->ForceClosed();
+  if (m_mailDB) {
+    nsresult rv3 = m_mailDB->Close(true);
+    if (NS_FAILED(rv3)) NS_WARNING("m_mailDB->Close(true) failed.");
+    m_mailDB = nullptr;  // code uniformity
+  }
+  // XXX we may need to check the return value of ForceClosed().
+  if (m_backupMailDB) {
+    m_backupMailDB->ForceClosed();
+    // Without the following statement,
+    // I experienced a double free
+    m_backupMailDB = nullptr;
+  }
 #ifdef DOING_JSFILTERS
   JSFilter_cleanup();
 #endif
 }
 
 // not an IMETHOD so we don't need to do error checking or return an error.
 // We only have one caller.
 void nsParseNewMailState::GetMsgWindow(nsIMsgWindow **aMsgWindow) {
@@ -1675,16 +1687,27 @@ int32_t nsParseNewMailState::PublishMsgH
           // Same for deleting it or moving it to trash.
           switch (duplicateAction) {
             case nsIMsgIncomingServer::deleteDups: {
               nsCOMPtr<nsIMsgPluggableStore> msgStore;
               nsresult rv =
                   m_downloadFolder->GetMsgStore(getter_AddRefs(msgStore));
               if (NS_SUCCEEDED(rv)) {
                 rv = msgStore->DiscardNewMessage(m_outputStream, m_newMsgHdr);
+                // Make sure that m_outputStream is closed in
+                // DiscardNewMessage above, because
+                // under Windows, opened files cannot be moved,
+                // renamed, copied, etc.
+
+                // We always set this to null since we close the stream
+                // irrespective of m_tempMessageStreamReusable value.
+                m_outputStream = nullptr;  // avoid accessing closed stream
+
+                // Delayed checking of DiscardNewMessage() error return
+
                 if (NS_FAILED(rv))
                   m_rootFolder->ThrowAlertMsg("dupDeleteFolderTruncateFailed",
                                               msgWindow);
               }
               m_mailDB->RemoveHeaderMdbRow(m_newMsgHdr);
             } break;
 
             case nsIMsgIncomingServer::moveDupsToTrash: {
@@ -2320,51 +2343,67 @@ nsresult nsParseNewMailState::EndMsgDown
 nsresult nsParseNewMailState::AppendMsgFromStream(nsIInputStream *fileStream,
                                                   nsIMsgDBHdr *aHdr,
                                                   uint32_t length,
                                                   nsIMsgFolder *destFolder) {
   nsCOMPtr<nsIMsgPluggableStore> store;
   nsCOMPtr<nsIOutputStream> destOutputStream;
   nsresult rv = destFolder->GetMsgStore(getter_AddRefs(store));
   NS_ENSURE_SUCCESS(rv, rv);
-  bool reusable;
-  rv = store->GetNewMsgOutputStream(destFolder, &aHdr, &reusable,
+  rv = store->GetNewMsgOutputStream(destFolder, &aHdr,
                                     getter_AddRefs(destOutputStream));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!m_ibuffer) {
     m_ibuffer_size = FILE_IO_BUFFER_SIZE;
     m_ibuffer = (char *)PR_Malloc(m_ibuffer_size);
     NS_ASSERTION(m_ibuffer != nullptr, "couldn't get memory to move msg");
   }
   m_ibuffer_fp = 0;
 
   while (length > 0 && m_ibuffer) {
     uint32_t nRead;
-    fileStream->Read(m_ibuffer,
-                     length > m_ibuffer_size ? m_ibuffer_size : length, &nRead);
+    rv = fileStream->Read(
+        m_ibuffer, length > m_ibuffer_size ? m_ibuffer_size : length, &nRead);
+    if (NS_FAILED(rv)) {
+      // XXX TODO/FIXME: We need a better error recovery strategy,
+      // etc.
+      // The read above DID return an error during the simulated
+      // test of interrupted remote CIFS mount for one's MAIL
+      // directory.  March 15, 2015
+      NS_WARNING("fileStream->Read (m_ibuffer, ...) returned error.");
+    }
     if (nRead == 0) break;
 
     uint32_t bytesWritten;
     // Check the number of bytes actually written to the stream.
-    destOutputStream->Write(m_ibuffer, nRead, &bytesWritten);
-    if (bytesWritten != nRead) {
-      destOutputStream->Close();
+
+    nsresult rv4 = destOutputStream->Write(m_ibuffer, nRead, &bytesWritten);
+    if (NS_FAILED(rv4) || bytesWritten != nRead) {
+      // XXX TODO Better network error handling.
+      // When the error was observed for read near line 2460, the close
+      // below also failed.  March 15, 2015
+
+      nsresult rv3 = destOutputStream->Close();
+      if (NS_FAILED(rv3)) NS_WARNING("destOutputStream->Close() failed;");
+      destOutputStream = nullptr;
+
       return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
     }
 
     length -= nRead;
   }
 
   NS_ASSERTION(length == 0,
                "didn't read all of original message in filter move");
 
   // non-reusable streams will get closed by the store.
-  if (reusable) destOutputStream->Close();
-  return store->FinishNewMessage(destOutputStream, aHdr);
+  nsresult rvfinal = store->FinishNewMessage(destOutputStream, aHdr);
+  destOutputStream = nullptr;  // code uniformity
+  return rvfinal;
 }
 
 /*
  * Moves message pointed to by mailHdr into folder destIFolder.
  * After successful move mailHdr is no longer usable by the caller.
  */
 nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
                                                       nsIMsgDatabase *sourceDB,
@@ -2424,35 +2463,53 @@ nsresult nsParseNewMailState::MoveIncorp
   nsCOMPtr<nsIMsgDatabase> destMailDB;
 
   if (!localFolder) return NS_MSG_POP_FILTER_TARGET_ERROR;
 
   // don't force upgrade in place - open the db here before we start writing to
   // the destination file because XP_Stat can return file size including bytes
   // written...
   rv = localFolder->GetDatabaseWOReparse(getter_AddRefs(destMailDB));
-  NS_WARNING_ASSERTION(destMailDB && NS_SUCCEEDED(rv),
-                       "failed to open mail db parsing folder");
+#ifdef DEBUG
+  // running TB under Linux using another Linux CIFS server as mail store
+  // failed the above line when network error occurred.
+  // 8055005: MailNews, failure, no = 5
+  if (NS_FAILED(rv)) {
+    fprintf(
+        stderr,
+        "(debug) localFolder->GetDatabaseWOReparse(getter_AddRefs(destMailDB)) "
+        "returned error rv=0x%" PRIx32 "\n",
+        static_cast<uint32_t>(rv));
+  }
+#endif
+  if (!(destMailDB && NS_SUCCEEDED(rv)))
+    NS_WARNING("failed to open mail db parsing folder");
+
   nsCOMPtr<nsIMsgDBHdr> newHdr;
 
   if (destMailDB)
     rv = destMailDB->CopyHdrFromExistingHdr(m_new_key, mailHdr, true,
                                             getter_AddRefs(newHdr));
   if (NS_SUCCEEDED(rv) && !newHdr) rv = NS_ERROR_UNEXPECTED;
 
   if (NS_FAILED(rv)) {
     destIFolder->ThrowAlertMsg("filterFolderHdrAddFailed", msgWindow);
   } else {
     rv = AppendMsgFromStream(inputStream, newHdr, messageLength, destIFolder);
     if (NS_FAILED(rv))
       destIFolder->ThrowAlertMsg("filterFolderWriteFailed", msgWindow);
   }
 
   if (NS_FAILED(rv)) {
-    if (destMailDB) destMailDB->Close(true);
+    if (destMailDB) {
+      destMailDB->Close(true);
+      nsresult rv3 = destMailDB->Close(true);
+      if (NS_FAILED(rv3)) NS_WARNING("destMailDB->Close() failed;");
+      destMailDB = nullptr;
+    }
 
     destIFolder->ReleaseSemaphore(myISupports);
 
     return NS_MSG_ERROR_WRITING_MAIL_FOLDER;
   }
 
   bool movedMsgIsNew = false;
   // if we have made it this far then the message has successfully been written
@@ -2497,17 +2554,24 @@ nsresult nsParseNewMailState::MoveIncorp
           EmptyCString());
     } else {
       NS_WARNING("Can't get folder for message that was moved.");
     }
   }
 
   nsCOMPtr<nsIMsgPluggableStore> store;
   rv = m_downloadFolder->GetMsgStore(getter_AddRefs(store));
-  if (store) store->DiscardNewMessage(m_outputStream, mailHdr);
+  if (store) {
+    nsresult rv2 = store->DiscardNewMessage(m_outputStream, mailHdr);
+    // we now have to close m_outputStream on the caller side.
+    m_outputStream = nullptr;  // avoid accessing closed stream
+    // delayed check of DiscardNewMessage() return value
+    if (NS_FAILED(rv2)) NS_WARNING("store->DiscardNewMessage(...) failed;");
+  }
+
   if (sourceDB) sourceDB->RemoveHeaderMdbRow(mailHdr);
 
   // update the folder size so we won't reparse.
   UpdateDBFolderInfo(destMailDB);
   destIFolder->UpdateSummaryTotals(true);
 
   destMailDB->Commit(nsMsgDBCommitType::kLargeCommit);
   return rv;