diff --git a/src/infrastructure/celerity/map/CelerityResourceMap.php b/src/infrastructure/celerity/map/CelerityResourceMap.php index 59fff93f34..5d0ec732fc 100644 --- a/src/infrastructure/celerity/map/CelerityResourceMap.php +++ b/src/infrastructure/celerity/map/CelerityResourceMap.php @@ -1,134 +1,134 @@ resourceMap = $resource_map; return $this; } public function resolveResources(array $symbols) { $map = array(); foreach ($symbols as $symbol) { if (!empty($map[$symbol])) { continue; } $this->resolveResource($map, $symbol); } return $map; } private function resolveResource(array &$map, $symbol) { if (empty($this->resourceMap[$symbol])) { throw new Exception( - "Attempting to resolve unknown resource, '{$symbol}'."); + "Attempting to resolve unknown Celerity resource, '{$symbol}'."); } $info = $this->resourceMap[$symbol]; foreach ($info['requires'] as $requires) { if (!empty($map[$requires])) { continue; } $this->resolveResource($map, $requires); } $map[$symbol] = $info; } public function setPackageMap($package_map) { $this->packageMap = $package_map; } public function packageResources(array $resolved_map) { $packaged = array(); $handled = array(); foreach ($resolved_map as $symbol => $info) { if (isset($handled[$symbol])) { continue; } if (empty($this->packageMap['reverse'][$symbol])) { $packaged[$symbol] = $info; } else { $package = $this->packageMap['reverse'][$symbol]; $package_info = $this->packageMap['packages'][$package]; $packaged[$package_info['name']] = $package_info; - foreach ($package_info['symbols'] as $symbol) { - $handled[$symbol] = true; + foreach ($package_info['symbols'] as $packaged_symbol) { + $handled[$packaged_symbol] = true; } } } return $packaged; } public function resolvePackage($package_hash) { $package = idx($this->packageMap['packages'], $package_hash); if (!$package) { return null; } $paths = array(); foreach ($package['symbols'] as $symbol) { $paths[] = $this->resourceMap[$symbol]['disk']; } return $paths; } public function lookupSymbolInformation($symbol) { return idx($this->resourceMap, $symbol); } public function lookupFileInformation($path) { if (empty($this->reverseMap)) { $this->reverseMap = array(); foreach ($this->resourceMap as $symbol => $data) { $data['provides'] = $symbol; $this->reverseMap[$data['disk']] = $data; } } return idx($this->reverseMap, $path); } } diff --git a/webroot/index.php b/webroot/index.php index 99420087f8..c9912c5cfc 100644 --- a/webroot/index.php +++ b/webroot/index.php @@ -1,239 +1,278 @@ ', where '' ". "is one of 'development', 'production', or a custom environment."); } if (!function_exists('mysql_connect')) { phabricator_fatal_config_error( "The PHP MySQL extension is not installed. This extension is required."); } if (!isset($_REQUEST['__path__'])) { phabricator_fatal_config_error( "__path__ is not set. Your rewrite rules are not configured correctly."); } if (get_magic_quotes_gpc()) { phabricator_fatal_config_error( "Your server is configured with PHP 'magic_quotes_gpc' enabled. This ". "feature is 'highly discouraged' by PHP's developers and you must ". "disable it to run Phabricator. Consult the PHP manual for instructions."); } +register_shutdown_function('phabricator_shutdown'); + require_once dirname(dirname(__FILE__)).'/conf/__init_conf__.php'; try { setup_aphront_basics(); $conf = phabricator_read_config_file($env); $conf['phabricator.env'] = $env; phutil_require_module('phabricator', 'infrastructure/env'); PhabricatorEnv::setEnvConfig($conf); phutil_require_module('phabricator', 'aphront/console/plugin/xhprof/api'); DarkConsoleXHProfPluginAPI::hookProfiler(); phutil_require_module('phabricator', 'aphront/console/plugin/errorlog/api'); PhutilErrorHandler::initialize(); } catch (Exception $ex) { - phabricator_fatal_config_error( - "[Exception] ".$ex->getMessage()); + phabricator_fatal("[Initialization Exception] ".$ex->getMessage()); } $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone'); if ($tz) { date_default_timezone_set($tz); } phutil_require_module('phabricator', 'aphront/console/plugin/errorlog/api'); phutil_require_module('phutil', 'error'); PhutilErrorHandler::setErrorListener( array('DarkConsoleErrorLogPluginAPI', 'handleErrors')); foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } if (PhabricatorEnv::getEnvConfig('phabricator.setup')) { PhabricatorSetup::runSetup(); return; } $host = $_SERVER['HTTP_HOST']; $path = $_REQUEST['__path__']; switch ($host) { default: $config_key = 'aphront.default-application-configuration-class'; $config_class = PhabricatorEnv::getEnvConfig($config_key); PhutilSymbolLoader::loadClass($config_class); $application = newv($config_class, array()); break; } $application->setHost($host); $application->setPath($path); $application->willBuildRequest(); $request = $application->buildRequest(); $application->setRequest($request); list($controller, $uri_data) = $application->buildController(); try { $response = $controller->willBeginExecution(); if (!$response) { $controller->willProcessRequest($uri_data); $response = $controller->processRequest(); } } catch (AphrontRedirectException $ex) { $response = id(new AphrontRedirectResponse()) ->setURI($ex->getURI()); } catch (Exception $ex) { $response = $application->handleException($ex); } -$response = $application->willSendResponse($response); - -$response->setRequest($request); - -$response_string = $response->buildResponseString(); +try { + $response = $application->willSendResponse($response); + $response->setRequest($request); + $response_string = $response->buildResponseString(); +} catch (Exception $ex) { + phabricator_fatal('[Rendering Exception] '.$ex->getMessage()); +} $code = $response->getHTTPResponseCode(); if ($code != 200) { header("HTTP/1.0 {$code}"); } $headers = $response->getCacheHeaders(); $headers = array_merge($headers, $response->getHeaders()); foreach ($headers as $header) { list($header, $value) = $header; header("{$header}: {$value}"); } // TODO: This shouldn't be possible in a production-configured environment. if (isset($_REQUEST['__profile__']) && ($_REQUEST['__profile__'] == 'all')) { $profile = DarkConsoleXHProfPluginAPI::stopProfiler(); $profile = '
'. ''. '>>> View Profile <<<'. ''. '
'; if (strpos($response_string, '') !== false) { $response_string = str_replace( '', ''.$profile, $response_string); } else { echo $profile; } } echo $response_string; - /** * @group aphront */ function setup_aphront_basics() { $aphront_root = dirname(dirname(__FILE__)); $libraries_root = dirname($aphront_root); $root = null; if (!empty($_SERVER['PHUTIL_LIBRARY_ROOT'])) { $root = $_SERVER['PHUTIL_LIBRARY_ROOT']; } ini_set('include_path', $libraries_root.':'.ini_get('include_path')); @include_once $root.'libphutil/src/__phutil_library_init__.php'; if (!@constant('__LIBPHUTIL__')) { echo "ERROR: Unable to load libphutil. Update your PHP 'include_path' to ". "include the parent directory of libphutil/.\n"; exit(1); } // Load Phabricator itself using the absolute path, so we never end up doing // anything surprising (loading index.php and libraries from different // directories). phutil_load_library($aphront_root.'/src'); phutil_load_library('arcanist/src'); + } function phabricator_fatal_config_error($msg) { - header('Content-Type: text/plain', $replace = true, $http_error = 500); - $error = "CONFIG ERROR: ".$msg."\n"; - - error_log($error); - echo $error; - + phabricator_fatal("CONFIG ERROR: ".$msg."\n"); die(); } function phabricator_detect_insane_memory_limit() { $memory_limit = ini_get('memory_limit'); $char_limit = 12; if (strlen($memory_limit) <= $char_limit) { return; } // colmdoyle ran into an issue on an Ubuntu box with Suhosin where his // 'memory_limit' was set to: // // 3232323232323232323232323232323232323232323232323232323232323232M // // Not a typo. A wizard did it. // // Anyway, with this 'memory_limit', the machine would immediately fatal // when executing the ini_set() later. I wasn't able to reproduce this on my // EC2 Ubuntu + Suhosin box, but verified that it caused the problem on his // machine and that setting it to a more sensible value fixed it. Since I // have no idea how to actually trigger the issue, we look for a coarse // approximation of it (a memory_limit setting more than 12 characters in // length). phabricator_fatal_config_error( "Your PHP 'memory_limit' is set to something ridiculous ". "(\"{$memory_limit}\"). Set it to a more reasonable value (it must be no ". "more than {$char_limit} characters long)."); } + +function phabricator_shutdown() { + $event = error_get_last(); + + if (!$event) { + return; + } + + if ($event['type'] != E_ERROR) { + return; + } + + $msg = ">>> UNRECOVERABLE FATAL ERROR <<<\n\n"; + if ($event) { + // Even though we should be emitting this as text-plain, escape things just + // to be sure since we can't really be sure what the program state is when + // we get here. + $msg .= phutil_escape_html($event['message'])."\n\n"; + $msg .= phutil_escape_html($event['file'].':'.$event['line']); + } + + // flip dem tables + $msg .= "\n\n\n"; + $msg .= "\xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb\x20\xef\xb8\xb5\x20\xc2\xaf". + "\x5c\x5f\x28\xe3\x83\x84\x29\x5f\x2f\xc2\xaf\x20\xef\xb8\xb5\x20". + "\xe2\x94\xbb\xe2\x94\x81\xe2\x94\xbb"; + + phabricator_fatal($msg); +} + +function phabricator_fatal($msg) { + header( + 'Content-Type: text/plain; charset=utf-8', + $replace = true, + $http_error = 500); + + error_log($msg); + echo $msg; + + exit(1); +}