Bug 1427012 - make the stream class used in printing more resilient to runtime errors, instead of crashing; r=bobowen
authorAlex Gaynor <agaynor@mozilla.com>
Fri, 05 Jan 2018 14:52:54 -0500
changeset 450227 7b813845b721a97bb5e2743912635c149f26039c
parent 450226 90da1b24e686f5350c9ab09720e1745eb2bdb286
child 450228 516bfb7086809b896dcabcc14be2a3b4c56cd33d
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbobowen
bugs1427012
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1427012 - make the stream class used in printing more resilient to runtime errors, instead of crashing; r=bobowen MozReview-Commit-ID: 6ExIvOAWfQX
layout/printing/DrawEventRecorder.h
--- a/layout/printing/DrawEventRecorder.h
+++ b/layout/printing/DrawEventRecorder.h
@@ -19,22 +19,24 @@ namespace layout {
 class PRFileDescStream : public mozilla::gfx::EventStream {
   // Most writes, as seen in the print IPC use case, are very small (<32 bytes),
   // with a small number of very large (>40KB) writes. Writes larger than this
   // value are not buffered.
   static const size_t kBufferSize = 1024;
 public:
   PRFileDescStream() : mFd(nullptr), mBuffer(nullptr), mBufferPos(0),
                        mGood(true) {}
+  PRFileDescStream(const PRFileDescStream& other) = delete;
+  ~PRFileDescStream() { Close(); }
 
   void OpenFD(PRFileDesc* aFd)
   {
     MOZ_ASSERT(!IsOpen());
     mFd = aFd;
-    mGood = true;
+    mGood = !!mFd;
     mBuffer.reset(new uint8_t[kBufferSize]);
     mBufferPos = 0;
   }
 
   void Close() {
     // We need to be API compatible with std::ostream, and so we silently handle
     // closes on a closed FD.
     if (IsOpen()) {
@@ -48,55 +50,67 @@ public:
 
   bool IsOpen() {
     return mFd != nullptr;
   }
 
   void Flush() {
     // See comment in Close().
     if (IsOpen() && mBufferPos > 0) {
-      PR_Write(mFd, static_cast<const void*>(mBuffer.get()), mBufferPos);
+      PRInt32 length =
+        PR_Write(mFd, static_cast<const void*>(mBuffer.get()), mBufferPos);
+      mGood = length >= 0 && static_cast<size_t>(length) == mBufferPos;
       mBufferPos = 0;
     }
   }
 
-  void Seek(PRInt32 aOffset, PRSeekWhence aWhence) {
+  void Seek(PRInt64 aOffset, PRSeekWhence aWhence)
+  {
     Flush();
-    PR_Seek(mFd, aOffset, aWhence);
+    PRInt64 pos = PR_Seek64(mFd, aOffset, aWhence);
+    mGood = pos != -1;
   }
 
   void write(const char* aData, size_t aSize) {
+    if (!good()) {
+      return;
+    }
+
     // See comment in Close().
     if (IsOpen()) {
       // If we're writing more data than could ever fit in our buffer, flush the
       // buffer and write directly.
       if (aSize > kBufferSize) {
         Flush();
-        PR_Write(mFd, static_cast<const void*>(aData), aSize);
-      // If our write could fit in our buffer, but doesn't because the buffer is
-      // partially full, write to the buffer, flush the buffer, and then write
-      // the rest of the data to the buffer.
+        PRInt32 length = PR_Write(mFd, static_cast<const void*>(aData), aSize);
+        mGood = length >= 0 && static_cast<size_t>(length) == aSize;
+      // If our write could fit in our buffer, but doesn't because the buffer
+      // is partially full, write to the buffer, flush the buffer, and then
+      // write the rest of the data to the buffer.
       } else if (aSize > AvailableBufferSpace()) {
         size_t length = AvailableBufferSpace();
         WriteToBuffer(aData, length);
         Flush();
 
-        MOZ_ASSERT(aSize <= kBufferSize);
         WriteToBuffer(aData + length, aSize - length);
       // Write fits in the buffer.
       } else {
         WriteToBuffer(aData, aSize);
       }
     }
   }
 
   void read(char* aOut, size_t aSize) {
+    if (!good()) {
+      return;
+    }
+
     Flush();
     PRInt32 res = PR_Read(mFd, static_cast<void*>(aOut), aSize);
-    mGood = res >= 0 && ((size_t)res == aSize);
+    mGood = res >= 0 && (static_cast<size_t>(res) == aSize);
   }
 
   bool good() {
     return mGood;
   }
 
 private:
   size_t AvailableBufferSpace() {