Changeset View
Changeset View
Standalone View
Standalone View
support/PhabricatorStartup.php
Show All 32 Lines | |||||
* @task hook Startup Hooks | * @task hook Startup Hooks | ||||
* @task apocalypse In Case Of Apocalypse | * @task apocalypse In Case Of Apocalypse | ||||
* @task validation Validation | * @task validation Validation | ||||
* @task ratelimit Rate Limiting | * @task ratelimit Rate Limiting | ||||
*/ | */ | ||||
final class PhabricatorStartup { | final class PhabricatorStartup { | ||||
private static $startTime; | private static $startTime; | ||||
private static $debugTimeLimit; | |||||
private static $globals = array(); | private static $globals = array(); | ||||
private static $capturingOutput; | private static $capturingOutput; | ||||
private static $rawInput; | private static $rawInput; | ||||
private static $oldMemoryLimit; | private static $oldMemoryLimit; | ||||
// TODO: For now, disable rate limiting entirely by default. We need to | // TODO: For now, disable rate limiting entirely by default. We need to | ||||
// iterate on it a bit for Conduit, some of the specific score levels, and | // iterate on it a bit for Conduit, some of the specific score levels, and | ||||
// to deal with NAT'd offices. | // to deal with NAT'd offices. | ||||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | public static function endOutputCapture() { | ||||
if (!self::$capturingOutput) { | if (!self::$capturingOutput) { | ||||
return null; | return null; | ||||
} | } | ||||
self::$capturingOutput = false; | self::$capturingOutput = false; | ||||
return ob_get_clean(); | return ob_get_clean(); | ||||
} | } | ||||
/* -( Debug Time Limit )--------------------------------------------------- */ | |||||
/** | |||||
* Set a time limit (in seconds) for the current script. After time expires, | |||||
* the script fatals. | |||||
* | |||||
* This works like `max_execution_time`, but prints out a useful stack trace | |||||
* when the time limit expires. This is primarily intended to make it easier | |||||
* to debug pages which hang by allowing extraction of a stack trace: set a | |||||
* short debug limit, then use the trace to figure out what's happening. | |||||
* | |||||
* The limit is implemented with a tick function, so enabling it implies | |||||
* some accounting overhead. | |||||
* | |||||
* @param int Time limit in seconds. | |||||
* @return void | |||||
*/ | |||||
public static function setDebugTimeLimit($limit) { | |||||
self::$debugTimeLimit = $limit; | |||||
static $initialized; | |||||
if (!$initialized) { | |||||
declare(ticks=1); | |||||
register_tick_function(array('PhabricatorStartup', 'onDebugTick')); | |||||
} | |||||
} | |||||
/** | |||||
* Callback tick function used by @{method:setDebugTimeLimit}. | |||||
* | |||||
* Fatals with a useful stack trace after the time limit expires. | |||||
* | |||||
* @return void | |||||
*/ | |||||
public static function onDebugTick() { | |||||
$limit = self::$debugTimeLimit; | |||||
if (!$limit) { | |||||
return; | |||||
} | |||||
$elapsed = (microtime(true) - self::getStartTime()); | |||||
if ($elapsed > $limit) { | |||||
$frames = array(); | |||||
foreach (debug_backtrace() as $frame) { | |||||
$file = isset($frame['file']) ? $frame['file'] : '-'; | |||||
$file = basename($file); | |||||
$line = isset($frame['line']) ? $frame['line'] : '-'; | |||||
$class = isset($frame['class']) ? $frame['class'].'->' : null; | |||||
$func = isset($frame['function']) ? $frame['function'].'()' : '?'; | |||||
$frames[] = "{$file}:{$line} {$class}{$func}"; | |||||
} | |||||
self::didFatal( | |||||
"Request aborted by debug time limit after {$limit} seconds.\n\n". | |||||
"STACK TRACE\n". | |||||
implode("\n", $frames)); | |||||
} | |||||
} | |||||
/* -( In Case of Apocalypse )---------------------------------------------- */ | /* -( In Case of Apocalypse )---------------------------------------------- */ | ||||
/** | /** | ||||
* Fatal the request completely in response to an exception, sending a plain | * Fatal the request completely in response to an exception, sending a plain | ||||
* text message to the client. Calls @{method:didFatal} internally. | * text message to the client. Calls @{method:didFatal} internally. | ||||
* | * | ||||
* @param string Brief description of the exception context, like | * @param string Brief description of the exception context, like | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | /* -( Validation )--------------------------------------------------------- */ | ||||
* @task validation | * @task validation | ||||
*/ | */ | ||||
private static function setupPHP() { | private static function setupPHP() { | ||||
error_reporting(E_ALL | E_STRICT); | error_reporting(E_ALL | E_STRICT); | ||||
self::$oldMemoryLimit = ini_get('memory_limit'); | self::$oldMemoryLimit = ini_get('memory_limit'); | ||||
ini_set('memory_limit', -1); | ini_set('memory_limit', -1); | ||||
// If we have libxml, disable the incredibly dangerous entity loader. | // If we have libxml, disable the incredibly dangerous entity loader. | ||||
if (function_exists('libxml_disable_entity_loader')) { | if (function_exists('libxml_disable_entity_loader')) { | ||||
joshuaspence: Great success! | |||||
Not Done Inline Actionsepriestley: awwyiss | |||||
libxml_disable_entity_loader(true); | libxml_disable_entity_loader(true); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* @task validation | * @task validation | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 464 Lines • Show Last 20 Lines |
Great success!