private static function initializeCommonEnvironment() { PhutilErrorHandler::initialize(); self::buildConfigurationSourceStack(); // Force a valid timezone. If both PHP and Phabricator configuration are // invalid, use UTC. $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone'); if ($tz) { @date_default_timezone_set($tz); } $ok = @date_default_timezone_set(date_default_timezone_get()); if (!$ok) { date_default_timezone_set('UTC'); } // Prepend '/support/bin' and append any paths to $PATH if we need to. $env_path = getenv('PATH'); $phabricator_path = dirname(phutil_get_library_root('phabricator')); $support_path = $phabricator_path . '/support/bin'; $env_path = $support_path . PATH_SEPARATOR . $env_path; $append_dirs = PhabricatorEnv::getEnvConfig('environment.append-paths'); if (!empty($append_dirs)) { $append_path = implode(PATH_SEPARATOR, $append_dirs); $env_path = $env_path . PATH_SEPARATOR . $append_path; } putenv('PATH=' . $env_path); // Write this back into $_ENV, too, so ExecFuture picks it up when creating // subprocess environments. $_ENV['PATH'] = $env_path; PhabricatorEventEngine::initialize(); $translation = PhabricatorEnv::newObjectFromConfig('translation.provider'); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations()); }
public static function registerErrorHandler() { // NOTE: This forces PhutilReadableSerializer to load, so that we are // able to handle errors which fire from inside autoloaders (PHP will not // reenter autoloaders). PhutilReadableSerializer::printableValue(null); PhutilErrorHandler::setErrorListener(array('DarkConsoleErrorLogPluginAPI', 'handleErrors')); }
/** * libphutil log function for development debugging. Takes any argument and * forwards it to registered listeners. This is essentially a more powerful * version of ##error_log()##. * * @param wild Any value you want printed to the error log or other registered * logs/consoles. * @param ... Other values to be logged. * @return wild Passed $value. */ function phlog($value) { // Get the caller information $trace = debug_backtrace(); $metadata = array('file' => $trace[0]['file'], 'line' => $trace[0]['line'], 'trace' => $trace); foreach (func_get_args() as $event) { PhutilErrorHandler::dispatchErrorMessage($event instanceof Exception ? PhutilErrorHandler::EXCEPTION : PhutilErrorHandler::PHLOG, $event, $metadata); } return $value; }
public function testProxyException() { $a = new Exception('a'); $b = new PhutilProxyException('b', $a); $c = new PhutilProxyException('c', $b); $this->assertEqual($a, $b->getPrevious()); $this->assertEqual($a, PhutilErrorHandler::getRootException($b)); $this->assertEqual($a, PhutilErrorHandler::getPreviousException($b)); $this->assertEqual($a, PhutilErrorHandler::getRootException($c)); $this->assertEqual($b, PhutilErrorHandler::getPreviousException($c)); }
function phutil_daemon_error_listener($event, $value, array $metadata) { $message = idx($metadata, 'default_message'); if ($message) { fwrite(STDERR, $message . "\n"); } if (idx($metadata, 'trace')) { $trace = PhutilErrorHandler::formatStacktrace($metadata['trace']); fwrite(STDERR, $trace . "\n"); } }
function phutil_daemon_error_listener($event, $value, array $metadata) { $console = PhutilConsole::getConsole(); $message = idx($metadata, 'default_message'); if ($message) { $console->writeErr("%s\n", $message); } if (idx($metadata, 'trace')) { $trace = PhutilErrorHandler::formatStacktrace($metadata['trace']); $console->writeErr("%s\n", $trace); } }
/** * libphutil log function for development debugging. Takes any argument and * forwards it to registered listeners. This is essentially a more powerful * version of ##error_log()##. * * NOTE: You must call ##PhutilErrorHandler::initialize()## before this will do * anything. * * @param wild Any value you want printed to the error log or other registered * logs/consoles. * @return wild Passed $value. * @group error */ function phlog($value) { if (!PhutilErrorHandler::hasInitialized()) { throw new Exception("Call to phlog() before PhutilErrorHandler::initialize()!"); } // Get the caller information $trace = debug_backtrace(); $file = $trace[0]['file']; $line = $trace[0]['line']; PhutilErrorHandler::dispatchErrorMessage($value instanceof Exception ? PhutilErrorHandler::EXCEPTION : PhutilErrorHandler::PHLOG, $value, array('file' => $file, 'line' => $line, 'trace' => $trace)); return $value; }
function __phutil_init_script__() { // Adjust the runtime language configuration to be reasonable and inline with // expectations. We do this first, then load libraries. // There may be some kind of auto-prepend script configured which starts an // output buffer. Discard any such output buffers so messages can be sent to // stdout (if a user wants to capture output from a script, there are a large // number of ways they can accomplish it legitimately; historically, we ran // into this on only one install which had some bizarre configuration, but it // was difficult to diagnose because the symptom is "no messages of any // kind"). while (ob_get_level() > 0) { ob_end_clean(); } error_reporting(E_ALL | E_STRICT); $config_map = array('display_errors' => true, 'log_errors' => true, 'error_log' => null, 'xdebug.max_nesting_level' => PHP_INT_MAX, 'memory_limit' => -1); foreach ($config_map as $config_key => $config_value) { ini_set($config_key, $config_value); } if (!ini_get('date.timezone')) { // If the timezone isn't set, PHP issues a warning whenever you try to parse // a date (like those from Git or Mercurial logs), even if the date contains // timezone information (like "PST" or "-0700") which makes the // environmental timezone setting is completely irrelevant. We never rely on // the system timezone setting in any capacity, so prevent PHP from flipping // out by setting it to a safe default (UTC) if it isn't set to some other // value. date_default_timezone_set('UTC'); } // Adjust `include_path`. ini_set('include_path', implode(PATH_SEPARATOR, array(dirname(dirname(__FILE__)) . '/externals/includes', ini_get('include_path')))); // Disable the insanely dangerous XML entity loader by default. if (function_exists('libxml_disable_entity_loader')) { libxml_disable_entity_loader(true); } // Now, load libphutil. $root = dirname(dirname(__FILE__)); require_once $root . '/src/__phutil_library_init__.php'; PhutilErrorHandler::initialize(); // If possible, install a signal handler for SIGHUP which prints the current // backtrace out to a named file. This is particularly helpful in debugging // hung/spinning processes. if (function_exists('pcntl_signal')) { pcntl_signal(SIGHUP, '__phutil_signal_handler__'); } }
private static function initializeCommonEnvironment() { PhutilErrorHandler::initialize(); self::buildConfigurationSourceStack(); // Force a valid timezone. If both PHP and Phabricator configuration are // invalid, use UTC. $tz = self::getEnvConfig('phabricator.timezone'); if ($tz) { @date_default_timezone_set($tz); } $ok = @date_default_timezone_set(date_default_timezone_get()); if (!$ok) { date_default_timezone_set('UTC'); } // Prepend '/support/bin' and append any paths to $PATH if we need to. $env_path = getenv('PATH'); $phabricator_path = dirname(phutil_get_library_root('phabricator')); $support_path = $phabricator_path . '/support/bin'; $env_path = $support_path . PATH_SEPARATOR . $env_path; $append_dirs = self::getEnvConfig('environment.append-paths'); if (!empty($append_dirs)) { $append_path = implode(PATH_SEPARATOR, $append_dirs); $env_path = $env_path . PATH_SEPARATOR . $append_path; } putenv('PATH=' . $env_path); // Write this back into $_ENV, too, so ExecFuture picks it up when creating // subprocess environments. $_ENV['PATH'] = $env_path; // If an instance identifier is defined, write it into the environment so // it's available to subprocesses. $instance = self::getEnvConfig('cluster.instance'); if (strlen($instance)) { putenv('PHABRICATOR_INSTANCE=' . $instance); $_ENV['PHABRICATOR_INSTANCE'] = $instance; } PhabricatorEventEngine::initialize(); // TODO: Add a "locale.default" config option once we have some reasonable // defaults which aren't silly nonsense. self::setLocaleCode('en_US'); }
/** * libphutil log function for development debugging. Takes any argument and * forwards it to registered listeners. This is essentially a more powerful * version of `error_log()`. * * @param wild Any value you want printed to the error log or other registered * logs/consoles. * @param ... Other values to be logged. * @return wild Passed $value. */ function phlog($value) { // Get the caller information. $trace = debug_backtrace(); $metadata = array('file' => $trace[0]['file'], 'line' => $trace[0]['line'], 'trace' => $trace); foreach (func_get_args() as $event) { $data = $metadata; if ($event instanceof Exception) { $type = PhutilErrorHandler::EXCEPTION; // If this is an exception, proxy it and generate a composite trace which // shows both where the phlog() was called and where the exception was // originally thrown from. $proxy = new PhutilProxyException('', $event); $trace = PhutilErrorHandler::getExceptionTrace($proxy); $data['trace'] = $trace; } else { $type = PhutilErrorHandler::PHLOG; } PhutilErrorHandler::dispatchErrorMessage($type, $event, $data); } return $value; }
public static function errorListener($event, $value, array $metadata) { // If the caller has redirected the error log to a file, PHP won't output // messages to stderr, so the overseer can't capture them. Install a // listener which just echoes errors to stderr, so the overseer is always // aware of errors. $console = PhutilConsole::getConsole(); $message = idx($metadata, 'default_message'); if ($message) { $console->writeErr("%s\n", $message); } if (idx($metadata, 'trace')) { $trace = PhutilErrorHandler::formatStacktrace($metadata['trace']); $console->writeErr("%s\n", $trace); } }
/** * Provide an optional listener callback which will receive all errors, * exceptions and debugging messages. It can then print them to a web console, * for example. * * See @{function:phutil_error_listener_example} for details about the * callback parameters and operation. * * @return void * @task config */ public static function setErrorListener($listener) { self::$errorListener = $listener; }
// Append any paths to $PATH if we need to. $paths = PhabricatorEnv::getEnvConfig('environment.append-paths'); if (!empty($paths)) { $current_env_path = getenv('PATH'); $new_env_paths = implode(':', $paths); putenv('PATH=' . $current_env_path . ':' . $new_env_paths); } // This is the earliest we can get away with this, we need env config first. PhabricatorAccessLog::init(); $access_log = PhabricatorAccessLog::getLog(); if ($access_log) { $access_log->setData(array('R' => idx($_SERVER, 'HTTP_REFERER', '-'), 'r' => idx($_SERVER, 'REMOTE_ADDR', '-'), 'M' => idx($_SERVER, 'REQUEST_METHOD', '-'))); } DarkConsoleXHProfPluginAPI::hookProfiler(); PhutilErrorHandler::initialize(); PhutilErrorHandler::setErrorListener(array('DarkConsoleErrorLogPluginAPI', 'handleErrors')); foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } if (PhabricatorEnv::getEnvConfig('phabricator.setup')) { try { PhabricatorSetup::runSetup(); } catch (Exception $ex) { echo "EXCEPTION!\n"; echo $ex; } return; } phabricator_detect_bad_base_uri(); $translation = PhabricatorEnv::newObjectFromConfig('translation.provider'); PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations());
* You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ $include_path = ini_get('include_path'); ini_set('include_path', $include_path . ':' . dirname(__FILE__) . '/../../'); require_once dirname(dirname(__FILE__)) . '/conf/__init_conf__.php'; $env = isset($_SERVER['PHABRICATOR_ENV']) ? $_SERVER['PHABRICATOR_ENV'] : getenv('PHABRICATOR_ENV'); if (!$env) { echo "Define PHABRICATOR_ENV before running this script.\n"; exit(1); } $conf = phabricator_read_config_file($env); $conf['phabricator.env'] = $env; phutil_require_module('phabricator', 'infrastructure/env'); PhabricatorEnv::setEnvConfig($conf); phutil_load_library('arcanist/src'); foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) { phutil_load_library($library); } PhutilErrorHandler::initialize(); $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone'); if ($tz) { date_default_timezone_set($tz); }
} PhutilErrorHandler::initialize(); function phutil_daemon_error_listener($event, $value, array $metadata) { $message = idx($metadata, 'default_message'); if ($message) { fwrite(STDERR, $message); } } if ($echo_to_stderr) { // If the caller has used "--log" to redirect the error log to a file, PHP // won't output it to stderr so the overseer can't capture it and won't // be able to send it to the web console. Install a listener which just echoes // errors to stderr, so we always get all the messages in the log and over // stdio, so they'll show up in the web console. PhutilErrorHandler::setErrorListener('phutil_daemon_error_listener'); } $daemon = array_shift($argv); if (!$daemon) { $args->printHelpAndExit(); } $daemon = newv($daemon, array($argv)); if ($trace_mode) { $daemon->setTraceMode(); } if ($trace_memory) { $daemon->setTraceMemory(); } if ($verbose) { $daemon->setVerbose(true); }
/** * Warns about use of deprecated behavior. */ function phutil_deprecated($what, $why) { PhutilErrorHandler::dispatchErrorMessage(PhutilErrorHandler::DEPRECATED, $what, array('why' => $why)); }
public function __construct() { PhutilErrorHandler::addErrorTrap($this); }