* @since 1.25
* @param Exception $e
*/
- public static function handleException( $e ) {
- global $wgFullyInitialised;
+ public static function handleException( Exception $e ) {
+ try {
+ // Rollback DBs to avoid transaction notices. This may fail
+ // to rollback some DB due to connection issues or exceptions.
+ // However, any sane DB driver will rollback implicitly anyway.
+ self::rollbackMasterChangesAndLog( $e );
+ } catch ( DBError $e2 ) {
+ // If the DB is unreacheable, rollback() will throw an error
+ // and the error report() method might need messages from the DB,
+ // which would result in an exception loop. PHP may escalate such
+ // errors to "Exception thrown without a stack frame" fatals, but
+ // it's better to be explicit here.
+ self::logException( $e2 );
+ }
- self::rollbackMasterChangesAndLog( $e );
self::logException( $e );
self::report( $e );
- // Final cleanup
- if ( $wgFullyInitialised ) {
- try {
- // uses $wgRequest, hence the $wgFullyInitialised condition
- wfLogProfilingData();
- } catch ( Exception $e ) {
- }
- }
-
// Exit value should be nonzero for the benefit of shell jobs
exit( 1 );
}
*/
public static function handleError( $level, $message, $file = null, $line = null ) {
// Map error constant to error name (reverse-engineer PHP error reporting)
+ $channel = 'error';
switch ( $level ) {
case E_ERROR:
case E_CORE_ERROR:
case E_RECOVERABLE_ERROR:
case E_PARSE:
$levelName = 'Error';
+ $channel = 'fatal';
break;
case E_WARNING:
case E_CORE_WARNING:
break;
case /* HHVM's FATAL_ERROR */ 16777217:
$levelName = 'Fatal';
+ $channel = 'fatal';
break;
default:
$levelName = 'Unknown error';
}
$e = new ErrorException( "PHP $levelName: $message", 0, $level, $file, $line );
- self::logError( $e );
+ self::logError( $e, $channel );
// This handler is for logging only. Return false will instruct PHP
// to continue regular handling.
if ( preg_match( "/Class (undefined: \w+|'\w+' not found)/",
$lastError['message']
) ) {
+ // @codingStandardsIgnoreStart Generic.Files.LineLength.TooLong
$msg = <<<TXT
{$msg}
Please see <a href="https://www.mediawiki.org/wiki/Download_from_Git#Fetch_external_libraries">mediawiki.org</a> for help on installing the required components.
TXT;
+ // @codingStandardsIgnoreEnd
}
$e = new ErrorException( $msg, 0, $lastError['type'] );
- self::logError( $e );
+ self::logError( $e, 'fatal' );
}
}
* returns the requested URL. Otherwise, returns false.
*
* @since 1.23
- * @return string|bool
+ * @return string|false
*/
public static function getURL() {
global $wgRequest;
* @param Exception $e
* @param bool $pretty Add non-significant whitespace to improve readability (default: false).
* @param int $escaping Bitfield consisting of FormatJson::.*_OK class constants.
- * @return string|bool JSON string if successful; false upon failure
+ * @return string|false JSON string if successful; false upon failure
*/
public static function jsonSerializeException( Exception $e, $pretty = false, $escaping = 0 ) {
global $wgLogExceptionBacktrace;
if ( $json !== false ) {
wfDebugLog( 'exception-json', $json, 'private' );
}
+
+ Hooks::run( 'LogException', array( $e, false ) );
}
}
*
* @since 1.25
* @param ErrorException $e
+ * @param string $channel
*/
- protected static function logError( ErrorException $e ) {
+ protected static function logError( ErrorException $e, $channel ) {
global $wgLogExceptionBacktrace;
// The set_error_handler callback is independent from error_reporting.
// Filter out unwanted errors manually (e.g. when wfSuppressWarnings is active).
- if ( ( error_reporting() & $e->getSeverity() ) !== 0 ) {
+ $suppressed = ( error_reporting() & $e->getSeverity() ) === 0;
+ if ( !$suppressed ) {
$log = self::getLogMessage( $e );
if ( $wgLogExceptionBacktrace ) {
- wfDebugLog( 'error', $log . "\n" . $e->getTraceAsString() );
+ wfDebugLog( $channel, $log . "\n" . $e->getTraceAsString() );
} else {
- wfDebugLog( 'error', $log );
+ wfDebugLog( $channel, $log );
}
}
// Include all errors in the json log (surpressed errors will be flagged)
$json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
if ( $json !== false ) {
- wfDebugLog( 'error-json', $json, 'private' );
+ wfDebugLog( "$channel-json", $json, 'private' );
}
+
+ Hooks::run( 'LogException', array( $e, $suppressed ) );
}
}