mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-14 02:42:40 +01:00
Add a configuration warning when memory_limit
will limit file uploads
Summary: Fixes T6011. See that task for discussion. We can detect when `memory_limit` will be the limiting factor for drag-and-drop uploads and warn administrators about it. Test Plan: Fiddled configuration values and hit, then resolved, the issue. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6011 Differential Revision: https://secure.phabricator.com/D10413
This commit is contained in:
parent
a6296a64a4
commit
8efea3abe9
4 changed files with 97 additions and 3 deletions
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
final class PhabricatorSetupCheckStorage extends PhabricatorSetupCheck {
|
final class PhabricatorSetupCheckStorage extends PhabricatorSetupCheck {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phutil-external-symbol class PhabricatorStartup
|
||||||
|
*/
|
||||||
protected function executeChecks() {
|
protected function executeChecks() {
|
||||||
$upload_limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit');
|
$upload_limit = PhabricatorEnv::getEnvConfig('storage.upload-size-limit');
|
||||||
if (!$upload_limit) {
|
if (!$upload_limit) {
|
||||||
|
@ -16,7 +19,63 @@ final class PhabricatorSetupCheckStorage extends PhabricatorSetupCheck {
|
||||||
->setName(pht('Upload Limit Not Yet Configured'))
|
->setName(pht('Upload Limit Not Yet Configured'))
|
||||||
->setMessage($message)
|
->setMessage($message)
|
||||||
->addPhabricatorConfig('storage.upload-size-limit');
|
->addPhabricatorConfig('storage.upload-size-limit');
|
||||||
|
} else {
|
||||||
|
$memory_limit = PhabricatorStartup::getOldMemoryLimit();
|
||||||
|
if ($memory_limit && ((int)$memory_limit > 0)) {
|
||||||
|
$memory_limit_bytes = phutil_parse_bytes($memory_limit);
|
||||||
|
$memory_usage_bytes = memory_get_usage();
|
||||||
|
$upload_limit_bytes = phutil_parse_bytes($upload_limit);
|
||||||
|
|
||||||
|
$available_bytes = ($memory_limit_bytes - $memory_usage_bytes);
|
||||||
|
|
||||||
|
if ($upload_limit_bytes > $available_bytes) {
|
||||||
|
$summary = pht(
|
||||||
|
'Your PHP memory limit is configured in a way that may prevent '.
|
||||||
|
'you from uploading large files.');
|
||||||
|
|
||||||
|
$message = pht(
|
||||||
|
'When you upload a file via drag-and-drop or the API, the entire '.
|
||||||
|
'file is buffered into memory before being written to permanent '.
|
||||||
|
'storage. Phabricator needs memory available to store these '.
|
||||||
|
'files while they are uploaded, but PHP is currently configured '.
|
||||||
|
'to limit the available memory.'.
|
||||||
|
"\n\n".
|
||||||
|
'Your Phabricator %s is currently set to a larger value (%s) than '.
|
||||||
|
'the amount of available memory (%s) that a PHP process has '.
|
||||||
|
'available to use, so uploads via drag-and-drop and the API will '.
|
||||||
|
'hit the memory limit before they hit other limits.'.
|
||||||
|
"\n\n".
|
||||||
|
'(Note that the application itself must also fit in available '.
|
||||||
|
'memory, so not all of the memory under the memory limit is '.
|
||||||
|
'available for buffering file uploads.)'.
|
||||||
|
"\n\n".
|
||||||
|
"The easiest way to resolve this issue is to set %s to %s in your ".
|
||||||
|
"PHP configuration, to disable the memory limit. There is ".
|
||||||
|
"usually little or no value to using this option to limit ".
|
||||||
|
"Phabricator process memory.".
|
||||||
|
"\n\n".
|
||||||
|
"You can also increase the limit, or decrease %s, or ignore this ".
|
||||||
|
"issue and accept that these upload mechanisms will be limited ".
|
||||||
|
"in the size of files they can handle.",
|
||||||
|
phutil_tag('tt', array(), 'storage.upload-size-limit'),
|
||||||
|
phutil_format_bytes($upload_limit_bytes),
|
||||||
|
phutil_format_bytes($available_bytes),
|
||||||
|
phutil_tag('tt', array(), 'memory_limit'),
|
||||||
|
phutil_tag('tt', array(), '-1'),
|
||||||
|
phutil_tag('tt', array(), 'storage.upload-size-limit'));
|
||||||
|
|
||||||
|
$this
|
||||||
|
->newIssue('php.memory_limit.upload')
|
||||||
|
->setName(pht('Memory Limit Restricts File Uploads'))
|
||||||
|
->setSummary($summary)
|
||||||
|
->setMessage($message)
|
||||||
|
->addPHPConfig('memory_limit')
|
||||||
|
->addPHPConfigOriginalValue('memory_limit', $memory_limit)
|
||||||
|
->addPhabricatorConfig('storage.upload-size-limit');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$local_path = PhabricatorEnv::getEnvConfig('storage.local-disk.path');
|
$local_path = PhabricatorEnv::getEnvConfig('storage.local-disk.path');
|
||||||
if (!$local_path) {
|
if (!$local_path) {
|
||||||
|
|
|
@ -16,6 +16,7 @@ final class PhabricatorSetupIssue {
|
||||||
private $phpConfig = array();
|
private $phpConfig = array();
|
||||||
private $commands = array();
|
private $commands = array();
|
||||||
private $mysqlConfig = array();
|
private $mysqlConfig = array();
|
||||||
|
private $originalPHPConfigValues = array();
|
||||||
|
|
||||||
public function addCommand($command) {
|
public function addCommand($command) {
|
||||||
$this->commands[] = $command;
|
$this->commands[] = $command;
|
||||||
|
@ -82,6 +83,28 @@ final class PhabricatorSetupIssue {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an explicit value to display when showing the user PHP configuration
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* If Phabricator has changed a value by the time a config issue is raised,
|
||||||
|
* you can provide the original value here so the UI makes sense. For example,
|
||||||
|
* we alter `memory_limit` during startup, so if the original value is not
|
||||||
|
* provided it will look like it is always set to `-1`.
|
||||||
|
*
|
||||||
|
* @param string PHP configuration option to provide a value for.
|
||||||
|
* @param string Explicit value to show in the UI.
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public function addPHPConfigOriginalValue($php_config, $value) {
|
||||||
|
$this->originalPHPConfigValues[$php_config] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPHPConfigOriginalValue($php_config, $default = null) {
|
||||||
|
return idx($this->originalPHPConfigValues, $php_config, $default);
|
||||||
|
}
|
||||||
|
|
||||||
public function getPHPConfig() {
|
public function getPHPConfig() {
|
||||||
return $this->phpConfig;
|
return $this->phpConfig;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
|
|
||||||
$configs = $issue->getPHPConfig();
|
$configs = $issue->getPHPConfig();
|
||||||
if ($configs) {
|
if ($configs) {
|
||||||
$description[] = $this->renderPHPConfig($configs);
|
$description[] = $this->renderPHPConfig($configs, $issue);
|
||||||
}
|
}
|
||||||
|
|
||||||
$configs = $issue->getMySQLConfig();
|
$configs = $issue->getMySQLConfig();
|
||||||
|
@ -243,7 +243,7 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderPHPConfig(array $configs) {
|
private function renderPHPConfig(array $configs, $issue) {
|
||||||
$table_info = phutil_tag(
|
$table_info = phutil_tag(
|
||||||
'p',
|
'p',
|
||||||
array(),
|
array(),
|
||||||
|
@ -253,7 +253,9 @@ final class PhabricatorSetupIssueView extends AphrontView {
|
||||||
|
|
||||||
$dict = array();
|
$dict = array();
|
||||||
foreach ($configs as $key) {
|
foreach ($configs as $key) {
|
||||||
$dict[$key] = ini_get($key);
|
$dict[$key] = $issue->getPHPConfigOriginalValue(
|
||||||
|
$key,
|
||||||
|
ini_get($key));
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = $this->renderValueTable($dict);
|
$table = $this->renderValueTable($dict);
|
||||||
|
|
|
@ -41,6 +41,7 @@ final class PhabricatorStartup {
|
||||||
private static $globals = array();
|
private static $globals = array();
|
||||||
private static $capturingOutput;
|
private static $capturingOutput;
|
||||||
private static $rawInput;
|
private static $rawInput;
|
||||||
|
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
|
||||||
|
@ -310,6 +311,7 @@ final class PhabricatorStartup {
|
||||||
*/
|
*/
|
||||||
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');
|
||||||
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.
|
||||||
|
@ -318,6 +320,14 @@ final class PhabricatorStartup {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task validation
|
||||||
|
*/
|
||||||
|
public static function getOldMemoryLimit() {
|
||||||
|
return self::$oldMemoryLimit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @task validation
|
* @task validation
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue