Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

FIX Flush on memory exhaustion and headers sent

  • Loading branch information...
commit 342058742c6b8e7f2aca77525c766439cefecfca 1 parent a1ea905
@hafriedlander hafriedlander authored
View
24 core/startup/ErrorControlChain.php
@@ -74,9 +74,33 @@ protected function lastErrorWasFatal() {
return $error && ($error['type'] & self::$fatal_errors) != 0;
}
+ protected function lastErrorWasMemoryExhaustion() {
+ $error = error_get_last();
+ $message = $error ? $error['message'] : '';
+ return stripos($message, 'memory') !== false && stripos($message, 'exhausted') !== false;
+ }
+
+ static $transtable = array(
+ 'k' => 1024,
+ 'm' => 1048576,
+ 'g' => 1073741824
+ );
+
+ protected function translateMemstring($memString) {
+ $char = strtolower(substr($memString, -1));
+ $fact = isset(self::$transtable[$char]) ? self::$transtable[$char] : 1;
+ return ((int)$memString) * $fact;
+ }
+
public function handleFatalError() {
if ($this->handleFatalErrors && $this->suppression) {
if ($this->lastErrorWasFatal()) {
+ if ($this->lastErrorWasMemoryExhaustion()) {
+ // Bump up memory limit by an arbitrary 10% / 10MB (whichever is bigger) since we've run out
+ $cur = $this->translateMemstring(ini_get('memory_limit'));
+ if ($cur != -1) ini_set('memory_limit', $cur + max(round($cur*0.1), 10000000));
+ }
+
$this->error = true;
$this->step();
}
View
9 core/startup/ParameterConfirmationToken.php
@@ -94,7 +94,14 @@ public function reloadWithToken() {
$location = "$proto://" . $host . BASE_URL . $url . ($params ? '?'.http_build_query($params) : '');
// And redirect
- header('location: '.$location, true, 302);
+ if (headers_sent()) {
+ echo "
+<script>location.href='$location';</script>
+<noscript><meta http-equiv='refresh' content='0; url=$location'></noscript>
+You are being redirected. If you are not redirected soon, <a href='$location'>click here to continue the flush</a>
+";
+ }
+ else header('location: '.$location, true, 302);
die;
}
}
View
41 tests/core/startup/ErrorControlChainTest.php
@@ -8,6 +8,11 @@
*/
class ErrorControlChainTest_Chain extends ErrorControlChain {
+ // Change function visibility to be testable directly
+ public function translateMemstring($memstring) {
+ return parent::translateMemstring($memstring);
+ }
+
function executeInSubprocess() {
// Get the path to the ErrorControlChain class
$classpath = SS_ClassLoader::instance()->getItemPath('ErrorControlChain');
@@ -114,6 +119,23 @@ function testErrorSuppression() {
->executeInSubprocess();
$this->assertEquals('Done', $out);
+
+ // Memory exhaustion
+
+ $chain = new ErrorControlChainTest_Chain();
+
+ list($out, $code) = $chain
+ ->then(function(){
+ ini_set('memory_limit', '10M');
+ $a = array();
+ while(1) $a[] = 1;
+ })
+ ->thenIfErrored(function(){
+ echo "Done";
+ })
+ ->executeInSubprocess();
+
+ $this->assertEquals('Done', $out);
}
function testExceptionSuppression() {
@@ -238,4 +260,23 @@ function testDoesntAffectHandledErrors() {
$this->assertContains("Good", $out);
}
+
+ function testMemoryConversion() {
+ $chain = new ErrorControlChainTest_Chain();
+
+ $this->assertEquals(200, $chain->translateMemstring('200'));
+ $this->assertEquals(300, $chain->translateMemstring('300'));
+
+ $this->assertEquals(2 * 1024, $chain->translateMemstring('2k'));
+ $this->assertEquals(3 * 1024, $chain->translateMemstring('3K'));
+
+ $this->assertEquals(2 * 1024 * 1024, $chain->translateMemstring('2m'));
+ $this->assertEquals(3 * 1024 * 1024, $chain->translateMemstring('3M'));
+
+ $this->assertEquals(2 * 1024 * 1024 * 1024, $chain->translateMemstring('2g'));
+ $this->assertEquals(3 * 1024 * 1024 * 1024, $chain->translateMemstring('3G'));
+
+ $this->assertEquals(200, $chain->translateMemstring('200foo'));
+ $this->assertEquals(300, $chain->translateMemstring('300foo'));
+ }
}
Please sign in to comment.
Something went wrong with that request. Please try again.