mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #2285 from hafriedlander/fix/flush_30
FIX Flush on memory exhaustion and when headers sent
This commit is contained in:
commit
f037cf0781
@ -54,6 +54,13 @@ do {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// GLOBALS AND DEFINE SETTING
|
// GLOBALS AND DEFINE SETTING
|
||||||
|
|
||||||
|
function stripslashes_recursively(&$array) {
|
||||||
|
foreach($array as $k => $v) {
|
||||||
|
if(is_array($v)) stripslashes_recursively($array[$k]);
|
||||||
|
else $array[$k] = stripslashes($v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A blank HTTP_HOST value is used to detect command-line execution.
|
* A blank HTTP_HOST value is used to detect command-line execution.
|
||||||
* We update the $_SERVER variable to contain data consistent with the rest of the application.
|
* We update the $_SERVER variable to contain data consistent with the rest of the application.
|
||||||
|
@ -164,13 +164,6 @@ function project() {
|
|||||||
return $project;
|
return $project;
|
||||||
}
|
}
|
||||||
|
|
||||||
function stripslashes_recursively(&$array) {
|
|
||||||
foreach($array as $k => $v) {
|
|
||||||
if(is_array($v)) stripslashes_recursively($array[$k]);
|
|
||||||
else $array[$k] = stripslashes($v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see i18n::_t()
|
* @see i18n::_t()
|
||||||
*/
|
*/
|
||||||
|
@ -74,9 +74,33 @@ class ErrorControlChain {
|
|||||||
return $error && ($error['type'] & self::$fatal_errors) != 0;
|
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() {
|
public function handleFatalError() {
|
||||||
if ($this->handleFatalErrors && $this->suppression) {
|
if ($this->handleFatalErrors && $this->suppression) {
|
||||||
if ($this->lastErrorWasFatal()) {
|
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->error = true;
|
||||||
$this->step();
|
$this->step();
|
||||||
}
|
}
|
||||||
|
@ -91,10 +91,17 @@ class ParameterConfirmationToken {
|
|||||||
unset($params['url']);
|
unset($params['url']);
|
||||||
|
|
||||||
// Join them all together into the original URL
|
// Join them all together into the original URL
|
||||||
$location = "$proto://" . $host . BASE_URL . $url . ($params ? '?'.http_build_query($params) : '');
|
$location = "$proto://" . $host . '/' . ltrim(BASE_URL, '/') . $url . ($params ? '?'.http_build_query($params) : '');
|
||||||
|
|
||||||
// And redirect
|
// 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;
|
die;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1222,8 +1222,12 @@ PHP
|
|||||||
$this->statusMessage("Checking that friendly URLs work...");
|
$this->statusMessage("Checking that friendly URLs work...");
|
||||||
$this->checkRewrite();
|
$this->checkRewrite();
|
||||||
} else {
|
} else {
|
||||||
|
require_once 'core/startup/ParameterConfirmationToken.php';
|
||||||
|
$token = new ParameterConfirmationToken('flush');
|
||||||
|
$params = http_build_query($token->params());
|
||||||
|
|
||||||
$destinationURL = 'index.php/' .
|
$destinationURL = 'index.php/' .
|
||||||
($this->checkModuleExists('cms') ? 'home/successfullyinstalled?flush=1' : '?flush=1');
|
($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
|
||||||
|
|
||||||
echo <<<HTML
|
echo <<<HTML
|
||||||
<li>SilverStripe successfully installed; I am now redirecting you to your SilverStripe site...</li>
|
<li>SilverStripe successfully installed; I am now redirecting you to your SilverStripe site...</li>
|
||||||
@ -1361,8 +1365,12 @@ TEXT;
|
|||||||
}
|
}
|
||||||
|
|
||||||
function checkRewrite() {
|
function checkRewrite() {
|
||||||
|
require_once 'core/startup/ParameterConfirmationToken.php';
|
||||||
|
$token = new ParameterConfirmationToken('flush');
|
||||||
|
$params = http_build_query($token->params());
|
||||||
|
|
||||||
$destinationURL = str_replace('install.php', '', $_SERVER['SCRIPT_NAME']) .
|
$destinationURL = str_replace('install.php', '', $_SERVER['SCRIPT_NAME']) .
|
||||||
($this->checkModuleExists('cms') ? 'home/successfullyinstalled?flush=1' : '?flush=1');
|
($this->checkModuleExists('cms') ? "home/successfullyinstalled?$params" : "?$params");
|
||||||
|
|
||||||
echo <<<HTML
|
echo <<<HTML
|
||||||
<li id="ModRewriteResult">Testing...</li>
|
<li id="ModRewriteResult">Testing...</li>
|
||||||
|
@ -8,6 +8,11 @@
|
|||||||
*/
|
*/
|
||||||
class ErrorControlChainTest_Chain extends ErrorControlChain {
|
class ErrorControlChainTest_Chain extends ErrorControlChain {
|
||||||
|
|
||||||
|
// Change function visibility to be testable directly
|
||||||
|
public function translateMemstring($memstring) {
|
||||||
|
return parent::translateMemstring($memstring);
|
||||||
|
}
|
||||||
|
|
||||||
function executeInSubprocess() {
|
function executeInSubprocess() {
|
||||||
// Get the path to the ErrorControlChain class
|
// Get the path to the ErrorControlChain class
|
||||||
$classpath = SS_ClassLoader::instance()->getItemPath('ErrorControlChain');
|
$classpath = SS_ClassLoader::instance()->getItemPath('ErrorControlChain');
|
||||||
@ -114,6 +119,23 @@ class ErrorControlChainTest extends SapphireTest {
|
|||||||
->executeInSubprocess();
|
->executeInSubprocess();
|
||||||
|
|
||||||
$this->assertEquals('Done', $out);
|
$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() {
|
function testExceptionSuppression() {
|
||||||
@ -238,4 +260,23 @@ class ErrorControlChainTest extends SapphireTest {
|
|||||||
|
|
||||||
$this->assertContains("Good", $out);
|
$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'));
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user