Title: [120013] trunk
Revision
120013
Author
[email protected]
Date
2012-06-11 15:29:32 -0700 (Mon, 11 Jun 2012)

Log Message

Crash in fast/files/read tests during Garbage Collection
https://bugs.webkit.org/show_bug.cgi?id=87165

Reviewed by Michael Saboff

Source/WebCore:

Fix previous fix for hasPendingActivity, and fix a bug in a complex
abort case as well--abort during the final progress event of a write
would hang the writer.

* Modules/filesystem/FileWriter.cpp:
(WebCore::FileWriter::stop):
(WebCore::FileWriter::write):
(WebCore::FileWriter::truncate):
(WebCore::FileWriter::didWrite):
(WebCore::FileWriter::didTruncate):
(WebCore::FileWriter::didFail):
(WebCore::FileWriter::completeAbort):
(WebCore::FileWriter::doOperation):
(WebCore::FileWriter::signalCompletion):

LayoutTests:

Simplify file-writer-abort-continue.js a bit, and add a new test case
for a write that gets aborted in the final progress event, which
previously would have hung the FileWriter.

* fast/filesystem/file-writer-abort-continue-expected.txt:
* fast/filesystem/resources/file-writer-abort-continue.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (120012 => 120013)


--- trunk/LayoutTests/ChangeLog	2012-06-11 22:16:11 UTC (rev 120012)
+++ trunk/LayoutTests/ChangeLog	2012-06-11 22:29:32 UTC (rev 120013)
@@ -1,3 +1,17 @@
+2012-06-05  Eric Uhrhane <[email protected]>
+
+        Crash in fast/files/read tests during Garbage Collection
+        https://bugs.webkit.org/show_bug.cgi?id=87165
+
+        Reviewed by Michael Saboff
+
+        Simplify file-writer-abort-continue.js a bit, and add a new test case
+        for a write that gets aborted in the final progress event, which
+        previously would have hung the FileWriter.
+
+        * fast/filesystem/file-writer-abort-continue-expected.txt:
+        * fast/filesystem/resources/file-writer-abort-continue.js:
+
 2012-06-11  Dongwoo Im  <[email protected]>
 
         WebAudio tests need to set WebKitWebAudioEnabled.

Modified: trunk/LayoutTests/fast/filesystem/file-writer-abort-continue-expected.txt (120012 => 120013)


--- trunk/LayoutTests/fast/filesystem/file-writer-abort-continue-expected.txt	2012-06-11 22:16:11 UTC (rev 120012)
+++ trunk/LayoutTests/fast/filesystem/file-writer-abort-continue-expected.txt	2012-06-11 22:29:32 UTC (rev 120013)
@@ -2,23 +2,38 @@
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
+PASS 1100000 is blobSize
 starting test
-PASS 1100000 is blobSize
+PASS Calling write.
 PASS Calling abort
 PASS Saw abort
+PASS writer.length is 0
 PASS Saw writeend 0.
+PASS Calling write.
+PASS writer.length is 1100000
+PASS Saw writeend 1.
+PASS Calling truncate.
 PASS writer.length is 0
-PASS followOnAction == 1 || followOnAction == 3 is true
-PASS 1100000 is blobSize
+PASS Saw writeend 2.
+PASS Calling write.
+PASS Calling abort at the end of the write
+PASS Saw abort
 PASS writer.length is 1100000
-PASS Saw writeend 1.
-PASS 1100000 is blobSize
+PASS Saw writeend 3.
+PASS Calling write.
+PASS writer.length is 2200000
+PASS Saw writeend 4.
+PASS Calling truncate.
+PASS writer.length is 0
+PASS Saw writeend 5.
+PASS Calling write.
 PASS Calling abort
 PASS Saw abort
-PASS Saw writeend 0.
-PASS writer.length is 1100000
-PASS followOnAction == 1 || followOnAction == 3 is true
+PASS writer.length is 0
+PASS Saw writeend 6.
+PASS Calling truncate.
 PASS writer.length is 7
+PASS Saw writeend 7.
 PASS All tests complete.
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/filesystem/resources/file-writer-abort-continue.js (120012 => 120013)


--- trunk/LayoutTests/fast/filesystem/resources/file-writer-abort-continue.js	2012-06-11 22:16:11 UTC (rev 120012)
+++ trunk/LayoutTests/fast/filesystem/resources/file-writer-abort-continue.js	2012-06-11 22:29:32 UTC (rev 120013)
@@ -11,42 +11,88 @@
 var sawWriteEnd;
 var writer;
 var expectedLength;
-var truncateLength = 7;
+var truncateLength;
 var blobSize = 1100000;
+var currentTest = 0;
+var blob = getBlob();
 
 var methodSet = [
   {  // Setup method set that writes, then aborts that write before completion.
     action : startWrite,
     verifyLength : 0,
     onwritestart : abortWrite,
+    onprogress : nop,
     onwrite : onError,
     onabort : logAbort,
-    onwriteend : checkLengthAndCallFollowOnAction
+    onwriteend : checkLengthAndStartNextTest
   },
   {  // Method set that does a complete write.
     action : startWrite,
     verifyLength : blobSize,
     onwritestart : nop,
+    onprogress : nop,
     onwrite : nop,
     onabort : onError,
     onwriteend : checkLengthAndStartNextTest
   },
-  {  // Setup method set that writes, then aborts that write before completion.
+  { // Method set that does a complete truncate, just to clean up.
+    action : startTruncate,
+    truncateLength : 0,
+    verifyLength : 0,
+    onwritestart : nop,
+    onprogress : nop,
+    onwrite : nop,
+    onabort : onError,
+    onwriteend : checkLengthAndStartNextTest
+  },
+  {  // Setup method set that writes, then aborts that write just at completion.
     action : startWrite,
-    verifyLength : blobSize,  // Left over from the previous test.
+    verifyLength : blobSize,
+    onwritestart : nop,
+    onprogress : abortOnComplete,
+    onwrite : nop,
+    onabort : logAbort,
+    onwriteend : checkLengthAndStartNextTest
+  },
+  {  // Method set that does a complete write.
+    action : startWrite,
+    verifyLength : blobSize * 2, // Add in leftovers from previous method.
+    onwritestart : nop,
+    onprogress : nop,
+    onwrite : nop,
+    onabort : onError,
+    onwriteend : checkLengthAndStartNextTest
+  },
+  { // Method set that does a complete truncate, just to clean up.
+    action : startTruncate,
+    truncateLength : 0,
+    verifyLength : 0,
+    onwritestart : nop,
+    onprogress : nop,
+    onwrite : nop,
+    onabort : onError,
+    onwriteend : checkLengthAndStartNextTest
+  },
+  {  // Setup method set that writes, then aborts that write as it starts.
+    action : startWrite,
+    verifyLength : 0,
     onwritestart : abortWrite,
+    onprogress : nop,
     onwrite : onError,
     onabort : logAbort,
-    onwriteend : checkLengthAndCallFollowOnAction
+    onwriteend : checkLengthAndStartNextTest
   },
   { // Method set that does a complete truncate.
     action : startTruncate,
-    verifyLength : truncateLength,
+    truncateLength : 7,
+    verifyLength : 7,
     onwritestart : nop,
+    onprogress : nop,
     onwrite : nop,
     onabort : onError,
-    onwriteend : checkLengthAndCompleteTest
-  }];
+    onwriteend : checkLengthAndStartNextTest
+  }
+];
 
 function nop() {
 }
@@ -59,49 +105,53 @@
     return new Blob(bb);
 }
 
-// These methods set up a write, abort it as soon as it starts, then initiate
-// the follow on action.
+function getBlob() {
+    // Let's make it about a megabyte.
+    var blob = tenXBlob(new Blob(["lorem ipsum"]));
+    blob = tenXBlob(blob);
+    blob = tenXBlob(blob);
+    blob = tenXBlob(blob);
+    blob = tenXBlob(blob);
+    var size = blob.size;
+    shouldBe("" + size, "blobSize");
+    return blob;
+}
+
 function abortWrite(e) {
     testPassed("Calling abort");
     writer.abort();
 }
 
+function abortOnComplete(e) {
+    if (e.loaded == e.total) {
+        testPassed("Calling abort at the end of the write");
+        writer.abort();
+    }
+}
+
 function logAbort(e) {
     testPassed("Saw abort");
 }
 
-function checkLengthAndCallFollowOnAction(e) {
-    testPassed("Saw writeend 0.");
-    shouldBe("writer.length", "" + expectedLength);
-    doFollowOnAction();
-}
-
-// For the second method set, verify completion and move on to the next test.
 function checkLengthAndStartNextTest(e) {
     shouldBe("writer.length", "" + expectedLength);
-    testPassed("Saw writeend 1.");
-    runTest(2, 3);
+    testPassed("Saw writeend " + currentTest + ".");
+    ++currentTest;
+    if (currentTest < methodSet.length)
+        runTest();
+    else {
+        testPassed("All tests complete.");
+        cleanUp();
+    }
 }
 
-function checkLengthAndCompleteTest(e) {
-    shouldBe("writer.length", "" + expectedLength);
-    testPassed("All tests complete.");
-    cleanUp();
-}
-
 function startWrite() {
-    // Let's make it about a megabyte.
-    var blob = tenXBlob(new Blob(["lorem ipsum"]));
-    blob = tenXBlob(blob);
-    blob = tenXBlob(blob);
-    blob = tenXBlob(blob);
-    blob = tenXBlob(blob);
-    var size = blob.size;
-    shouldBe("" + size, "blobSize");
+    testPassed("Calling write.");
     writer.write(blob);
 }
 
 function startTruncate() {
+    testPassed("Calling truncate.");
     writer.truncate(truncateLength);
 }
 
@@ -111,26 +161,22 @@
     var methods = methodSet[methodSetIndex];
     writer._onabort_ = methods.onabort;
     writer._onwritestart_ = methods.onwritestart;
+    writer._onprogress_ = methods.onprogress;
     writer._onwrite_ = methods.onwrite;
     writer._onwriteend_ = methods.onwriteend;
     expectedLength = methods.verifyLength;
+    truncateLength = methods.truncateLength;
     methods.action();
 }
 
-function runTest(initIndex, testIndex) {
-    followOnAction = testIndex;
-    setupWriter(initIndex, writer);
+function runTest() {
+    setupWriter(currentTest, writer);
 }
 
-function doFollowOnAction() {
-    shouldBeTrue("followOnAction == 1 || followOnAction == 3");
-    setupWriter(followOnAction, writer);
-}
-
 var jsTestIsAsync = true;
 setupAndRunTest(2*1024*1024, 'file-writer-abort',
                 function (fileEntry, fileWriter) {
                     fileEntryForCleanup = fileEntry;
                     writer = fileWriter;
-                    runTest(0, 1);
+                    runTest();
                 });

Modified: trunk/Source/WebCore/ChangeLog (120012 => 120013)


--- trunk/Source/WebCore/ChangeLog	2012-06-11 22:16:11 UTC (rev 120012)
+++ trunk/Source/WebCore/ChangeLog	2012-06-11 22:29:32 UTC (rev 120013)
@@ -1,3 +1,25 @@
+2012-06-05  Eric Uhrhane <[email protected]>
+
+        Crash in fast/files/read tests during Garbage Collection
+        https://bugs.webkit.org/show_bug.cgi?id=87165
+
+        Reviewed by Michael Saboff
+
+        Fix previous fix for hasPendingActivity, and fix a bug in a complex
+        abort case as well--abort during the final progress event of a write
+        would hang the writer.
+
+        * Modules/filesystem/FileWriter.cpp:
+        (WebCore::FileWriter::stop):
+        (WebCore::FileWriter::write):
+        (WebCore::FileWriter::truncate):
+        (WebCore::FileWriter::didWrite):
+        (WebCore::FileWriter::didTruncate):
+        (WebCore::FileWriter::didFail):
+        (WebCore::FileWriter::completeAbort):
+        (WebCore::FileWriter::doOperation):
+        (WebCore::FileWriter::signalCompletion):
+
 2012-06-11  Shawn Singh  <[email protected]>
 
         [chromium] Implement position:fixed in compositor thread

Modified: trunk/Source/WebCore/Modules/filesystem/FileWriter.cpp (120012 => 120013)


--- trunk/Source/WebCore/Modules/filesystem/FileWriter.cpp	2012-06-11 22:16:11 UTC (rev 120012)
+++ trunk/Source/WebCore/Modules/filesystem/FileWriter.cpp	2012-06-11 22:29:32 UTC (rev 120013)
@@ -90,8 +90,6 @@
         return;
     doOperation(OperationAbort);
     m_readyState = DONE;
-
-    setPendingActivity(this);
 }
 
 void FileWriter::write(Blob* data, ExceptionCode& ec)
@@ -112,8 +110,6 @@
         return;
     }
 
-    setPendingActivity(this);
-
     m_blobBeingWritten = data;
     m_readyState = WRITING;
     m_bytesWritten = 0;
@@ -155,8 +151,6 @@
         return;
     }
 
-    setPendingActivity(this);
-
     m_readyState = WRITING;
     m_bytesWritten = 0;
     m_bytesToWrite = 0;
@@ -198,15 +192,19 @@
     setPosition(position() + bytes);
     if (position() > length())
         setLength(position());
+    if (complete) {
+        m_blobBeingWritten.clear();
+        m_operationInProgress = OperationNone;
+    }
     // TODO: Throttle to no more frequently than every 50ms.
     int numAborts = m_numAborts;
     fireEvent(eventNames().progressEvent);
     // We could get an abort in the handler for this event. If we do, it's
     // already handled the cleanup and signalCompletion call.
-    if (complete && numAborts == m_numAborts) {
-        m_blobBeingWritten.clear();
-        m_operationInProgress = OperationNone;
-        signalCompletion(FileError::OK);
+    if (complete) {
+      if (numAborts == m_numAborts)
+          signalCompletion(FileError::OK);
+      unsetPendingActivity(this);
     }
 }
 
@@ -223,6 +221,7 @@
         setPosition(length());
     m_operationInProgress = OperationNone;
     signalCompletion(FileError::OK);
+    unsetPendingActivity(this);
 }
 
 void FileWriter::didFail(FileError::ErrorCode code)
@@ -239,6 +238,7 @@
     m_blobBeingWritten.clear();
     m_operationInProgress = OperationNone;
     signalCompletion(code);
+    unsetPendingActivity(this);
 }
 
 void FileWriter::completeAbort()
@@ -248,6 +248,7 @@
     Operation operation = m_queuedOperation;
     m_queuedOperation = OperationNone;
     doOperation(operation);
+    unsetPendingActivity(this);
 }
 
 void FileWriter::doOperation(Operation operation)
@@ -258,12 +259,14 @@
         ASSERT(m_truncateLength == -1);
         ASSERT(m_blobBeingWritten.get());
         ASSERT(m_readyState == WRITING);
+        setPendingActivity(this);
         writer()->write(position(), m_blobBeingWritten.get());
         break;
     case OperationTruncate:
         ASSERT(m_operationInProgress == OperationNone);
         ASSERT(m_truncateLength >= 0);
         ASSERT(m_readyState == WRITING);
+        setPendingActivity(this);
         writer()->truncate(m_truncateLength);
         break;
     case OperationNone:
@@ -275,6 +278,8 @@
     case OperationAbort:
         if (m_operationInProgress == OperationWrite || m_operationInProgress == OperationTruncate)
             writer()->abort();
+        else if (m_operationInProgress != OperationAbort)
+            operation = OperationNone;
         m_queuedOperation = OperationNone;
         m_blobBeingWritten.clear();
         m_truncateLength = -1;
@@ -297,9 +302,6 @@
     } else
         fireEvent(eventNames().writeEvent);
     fireEvent(eventNames().writeendEvent);
-    
-    // All possible events have fired and we're done, no more pending activity.
-    unsetPendingActivity(this);
 }
 
 void FileWriter::fireEvent(const AtomicString& type)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to