Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/debug/ErrorHandler.php @ 12:7a779792577d
Update Drupal core to v8.4.5 (via Composer)
author | Chris Cannam |
---|---|
date | Fri, 23 Feb 2018 15:52:07 +0000 |
parents | 4c8ae668cc8c |
children | 5fb285c0d0e3 |
comparison
equal
deleted
inserted
replaced
11:bfffd8d7479a | 12:7a779792577d |
---|---|
98 | 98 |
99 private static $reservedMemory; | 99 private static $reservedMemory; |
100 private static $stackedErrors = array(); | 100 private static $stackedErrors = array(); |
101 private static $stackedErrorLevels = array(); | 101 private static $stackedErrorLevels = array(); |
102 private static $toStringException = null; | 102 private static $toStringException = null; |
103 private static $silencedErrorCache = array(); | |
104 private static $silencedErrorCount = 0; | |
103 private static $exitCode = 0; | 105 private static $exitCode = 0; |
104 | 106 |
105 /** | 107 /** |
106 * Registers the error handler. | 108 * Registers the error handler. |
107 * | 109 * |
130 | 132 |
131 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) { | 133 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) { |
132 $handler = $prev[0]; | 134 $handler = $prev[0]; |
133 $replace = false; | 135 $replace = false; |
134 } | 136 } |
135 if ($replace || !$prev) { | 137 if (!$replace && $prev) { |
136 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException'))); | 138 restore_error_handler(); |
139 } | |
140 if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] === $handler) { | |
141 restore_exception_handler(); | |
137 } else { | 142 } else { |
138 restore_error_handler(); | 143 $handler->setExceptionHandler($prev); |
139 } | 144 } |
140 | 145 |
141 $handler->throwAt(E_ALL & $handler->thrownErrors, true); | 146 $handler->throwAt(E_ALL & $handler->thrownErrors, true); |
142 | 147 |
143 return $handler; | 148 return $handler; |
405 | 410 |
406 if (null !== self::$toStringException) { | 411 if (null !== self::$toStringException) { |
407 $errorAsException = self::$toStringException; | 412 $errorAsException = self::$toStringException; |
408 self::$toStringException = null; | 413 self::$toStringException = null; |
409 } elseif (!$throw && !($type & $level)) { | 414 } elseif (!$throw && !($type & $level)) { |
410 $errorAsException = new SilencedErrorContext($type, $file, $line); | 415 if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { |
416 $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array(); | |
417 $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); | |
418 } elseif (isset(self::$silencedErrorCache[$id][$message])) { | |
419 $lightTrace = null; | |
420 $errorAsException = self::$silencedErrorCache[$id][$message]; | |
421 ++$errorAsException->count; | |
422 } else { | |
423 $lightTrace = array(); | |
424 $errorAsException = null; | |
425 } | |
426 | |
427 if (100 < ++self::$silencedErrorCount) { | |
428 self::$silencedErrorCache = $lightTrace = array(); | |
429 self::$silencedErrorCount = 1; | |
430 } | |
431 if ($errorAsException) { | |
432 self::$silencedErrorCache[$id][$message] = $errorAsException; | |
433 } | |
434 if (null === $lightTrace) { | |
435 return; | |
436 } | |
411 } else { | 437 } else { |
412 if ($scope) { | 438 if ($scope) { |
413 $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); | 439 $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); |
414 } else { | 440 } else { |
415 $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); | 441 $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); |
416 } | 442 } |
417 | 443 |
418 // Clean the trace by removing function arguments and the first frames added by the error handler itself. | 444 // Clean the trace by removing function arguments and the first frames added by the error handler itself. |
419 if ($throw || $this->tracedErrors & $type) { | 445 if ($throw || $this->tracedErrors & $type) { |
420 $backtrace = $backtrace ?: $errorAsException->getTrace(); | 446 $backtrace = $backtrace ?: $errorAsException->getTrace(); |
421 $lightTrace = $backtrace; | 447 $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); |
422 | |
423 for ($i = 0; isset($backtrace[$i]); ++$i) { | |
424 if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { | |
425 $lightTrace = array_slice($lightTrace, 1 + $i); | |
426 break; | |
427 } | |
428 } | |
429 if (!($throw || $this->scopedErrors & $type)) { | |
430 for ($i = 0; isset($lightTrace[$i]); ++$i) { | |
431 unset($lightTrace[$i]['args']); | |
432 } | |
433 } | |
434 $this->traceReflector->setValue($errorAsException, $lightTrace); | 448 $this->traceReflector->setValue($errorAsException, $lightTrace); |
435 } else { | 449 } else { |
436 $this->traceReflector->setValue($errorAsException, array()); | 450 $this->traceReflector->setValue($errorAsException, array()); |
437 } | 451 } |
438 } | 452 } |
485 } elseif (self::$stackedErrorLevels) { | 499 } elseif (self::$stackedErrorLevels) { |
486 self::$stackedErrors[] = array( | 500 self::$stackedErrors[] = array( |
487 $this->loggers[$type][0], | 501 $this->loggers[$type][0], |
488 ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, | 502 ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, |
489 $logMessage, | 503 $logMessage, |
490 array('exception' => $errorAsException), | 504 $errorAsException ? array('exception' => $errorAsException) : array(), |
491 ); | 505 ); |
492 } else { | 506 } else { |
493 try { | 507 try { |
494 $this->isRecursive = true; | 508 $this->isRecursive = true; |
495 $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; | 509 $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; |
496 $this->loggers[$type][0]->log($level, $logMessage, array('exception' => $errorAsException)); | 510 $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array()); |
497 } finally { | 511 } finally { |
498 $this->isRecursive = false; | 512 $this->isRecursive = false; |
499 } | 513 } |
500 } | 514 } |
501 | 515 |
517 } | 531 } |
518 if (!$exception instanceof \Exception) { | 532 if (!$exception instanceof \Exception) { |
519 $exception = new FatalThrowableError($exception); | 533 $exception = new FatalThrowableError($exception); |
520 } | 534 } |
521 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR; | 535 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR; |
536 $handlerException = null; | |
522 | 537 |
523 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { | 538 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { |
524 if ($exception instanceof FatalErrorException) { | 539 if ($exception instanceof FatalErrorException) { |
525 if ($exception instanceof FatalThrowableError) { | 540 if ($exception instanceof FatalThrowableError) { |
526 $error = array( | 541 $error = array( |
532 } else { | 547 } else { |
533 $message = 'Fatal '.$exception->getMessage(); | 548 $message = 'Fatal '.$exception->getMessage(); |
534 } | 549 } |
535 } elseif ($exception instanceof \ErrorException) { | 550 } elseif ($exception instanceof \ErrorException) { |
536 $message = 'Uncaught '.$exception->getMessage(); | 551 $message = 'Uncaught '.$exception->getMessage(); |
537 if ($exception instanceof ContextErrorException) { | |
538 $e['context'] = $exception->getContext(); | |
539 } | |
540 } else { | 552 } else { |
541 $message = 'Uncaught Exception: '.$exception->getMessage(); | 553 $message = 'Uncaught Exception: '.$exception->getMessage(); |
542 } | 554 } |
543 } | 555 } |
544 if ($this->loggedErrors & $type) { | 556 if ($this->loggedErrors & $type) { |
554 $exception = $e; | 566 $exception = $e; |
555 break; | 567 break; |
556 } | 568 } |
557 } | 569 } |
558 } | 570 } |
559 if (empty($this->exceptionHandler)) { | |
560 throw $exception; // Give back $exception to the native handler | |
561 } | |
562 try { | 571 try { |
563 call_user_func($this->exceptionHandler, $exception); | 572 if (null !== $this->exceptionHandler) { |
573 return \call_user_func($this->exceptionHandler, $exception); | |
574 } | |
575 $handlerException = $handlerException ?: $exception; | |
564 } catch (\Exception $handlerException) { | 576 } catch (\Exception $handlerException) { |
565 } catch (\Throwable $handlerException) { | 577 } catch (\Throwable $handlerException) { |
566 } | 578 } |
567 if (isset($handlerException)) { | 579 $this->exceptionHandler = null; |
568 $this->exceptionHandler = null; | 580 if ($exception === $handlerException) { |
569 $this->handleException($handlerException); | 581 self::$reservedMemory = null; // Disable the fatal error handler |
570 } | 582 throw $exception; // Give back $exception to the native handler |
583 } | |
584 $this->handleException($handlerException); | |
571 } | 585 } |
572 | 586 |
573 /** | 587 /** |
574 * Shutdown registered function for handling PHP fatal errors. | 588 * Shutdown registered function for handling PHP fatal errors. |
575 * | 589 * |
581 { | 595 { |
582 if (null === self::$reservedMemory) { | 596 if (null === self::$reservedMemory) { |
583 return; | 597 return; |
584 } | 598 } |
585 | 599 |
586 self::$reservedMemory = null; | 600 $handler = self::$reservedMemory = null; |
587 | 601 $handlers = array(); |
588 $handler = set_error_handler('var_dump'); | 602 $previousHandler = null; |
589 $handler = is_array($handler) ? $handler[0] : null; | 603 $sameHandlerLimit = 10; |
590 restore_error_handler(); | 604 |
591 | 605 while (!is_array($handler) || !$handler[0] instanceof self) { |
592 if (!$handler instanceof self) { | 606 $handler = set_exception_handler('var_dump'); |
607 restore_exception_handler(); | |
608 | |
609 if (!$handler) { | |
610 break; | |
611 } | |
612 restore_exception_handler(); | |
613 | |
614 if ($handler !== $previousHandler) { | |
615 array_unshift($handlers, $handler); | |
616 $previousHandler = $handler; | |
617 } elseif (0 === --$sameHandlerLimit) { | |
618 $handler = null; | |
619 break; | |
620 } | |
621 } | |
622 foreach ($handlers as $h) { | |
623 set_exception_handler($h); | |
624 } | |
625 if (!$handler) { | |
593 return; | 626 return; |
594 } | 627 } |
628 if ($handler !== $h) { | |
629 $handler[0]->setExceptionHandler($h); | |
630 } | |
631 $handler = $handler[0]; | |
632 $handlers = array(); | |
595 | 633 |
596 if ($exit = null === $error) { | 634 if ($exit = null === $error) { |
597 $error = error_get_last(); | 635 $error = error_get_last(); |
598 } | 636 } |
599 | 637 |
642 * PHP has a compile stage where it behaves unusually. To workaround it, | 680 * PHP has a compile stage where it behaves unusually. To workaround it, |
643 * we plug an error handler that only stacks errors for later. | 681 * we plug an error handler that only stacks errors for later. |
644 * | 682 * |
645 * The most important feature of this is to prevent | 683 * The most important feature of this is to prevent |
646 * autoloading until unstackErrors() is called. | 684 * autoloading until unstackErrors() is called. |
685 * | |
686 * @deprecated since version 3.4, to be removed in 4.0. | |
647 */ | 687 */ |
648 public static function stackErrors() | 688 public static function stackErrors() |
649 { | 689 { |
690 @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); | |
691 | |
650 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); | 692 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); |
651 } | 693 } |
652 | 694 |
653 /** | 695 /** |
654 * Unstacks stacked errors and forwards to the logger. | 696 * Unstacks stacked errors and forwards to the logger. |
697 * | |
698 * @deprecated since version 3.4, to be removed in 4.0. | |
655 */ | 699 */ |
656 public static function unstackErrors() | 700 public static function unstackErrors() |
657 { | 701 { |
702 @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); | |
703 | |
658 $level = array_pop(self::$stackedErrorLevels); | 704 $level = array_pop(self::$stackedErrorLevels); |
659 | 705 |
660 if (null !== $level) { | 706 if (null !== $level) { |
661 $errorReportingLevel = error_reporting($level); | 707 $errorReportingLevel = error_reporting($level); |
662 if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) { | 708 if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) { |
688 new UndefinedFunctionFatalErrorHandler(), | 734 new UndefinedFunctionFatalErrorHandler(), |
689 new UndefinedMethodFatalErrorHandler(), | 735 new UndefinedMethodFatalErrorHandler(), |
690 new ClassNotFoundFatalErrorHandler(), | 736 new ClassNotFoundFatalErrorHandler(), |
691 ); | 737 ); |
692 } | 738 } |
739 | |
740 private function cleanTrace($backtrace, $type, $file, $line, $throw) | |
741 { | |
742 $lightTrace = $backtrace; | |
743 | |
744 for ($i = 0; isset($backtrace[$i]); ++$i) { | |
745 if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { | |
746 $lightTrace = array_slice($lightTrace, 1 + $i); | |
747 break; | |
748 } | |
749 } | |
750 if (!($throw || $this->scopedErrors & $type)) { | |
751 for ($i = 0; isset($lightTrace[$i]); ++$i) { | |
752 unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); | |
753 } | |
754 } | |
755 | |
756 return $lightTrace; | |
757 } | |
693 } | 758 } |